From 1a2bf757b6caaea41e37a20e11593c623b477bc4 Mon Sep 17 00:00:00 2001 From: William Brown Date: Mon, 6 Nov 2017 17:05:30 +1000 Subject: [PATCH] Ticket lib389 3 - python 3 support for betxn test Bug Description: Support python 3 for betxn test. Fix Description: python 3 support for betxn test, including addition of rename supprot for mapped objects. https://pagure.io/lib389/issue/3 Author: wibrown Review by: ??? --- dirsrvtests/tests/suites/betxns/betxn_test.py | 179 +++++++++----------------- src/lib389/lib389/_mapped_object.py | 31 +++++ 2 files changed, 94 insertions(+), 116 deletions(-) diff --git a/dirsrvtests/tests/suites/betxns/betxn_test.py b/dirsrvtests/tests/suites/betxns/betxn_test.py index 1754964..9a6e835 100644 --- a/dirsrvtests/tests/suites/betxns/betxn_test.py +++ b/dirsrvtests/tests/suites/betxns/betxn_test.py @@ -12,23 +12,17 @@ from lib389.tasks import * from lib389.utils import * from lib389.topologies import topology_st +from lib389.plugins import SevenBitCheckPlugin, AttributeUniquenessPlugin, MemberOfPlugin + +from lib389.idm.user import UserAccounts, TEST_USER_PROPERTIES +from lib389.idm.group import Groups + from lib389._constants import DEFAULT_SUFFIX, PLUGIN_7_BIT_CHECK, PLUGIN_ATTR_UNIQUENESS, PLUGIN_MEMBER_OF logging.getLogger(__name__).setLevel(logging.DEBUG) log = logging.getLogger(__name__) - -@pytest.fixture(scope='module') -def dynamic_plugins(topology_st): - """Enable dynamic plugins - makes plugin testing much easier""" - try: - topology_st.standalone.modify_s(DN_CONFIG, [(ldap.MOD_REPLACE, 'nsslapd-dynamic-plugins', 'on')]) - except ldap.LDAPError as e: - ldap.error('Failed to enable dynamic plugin!' + e.message['desc']) - assert False - - -def test_betxt_7bit(topology_st, dynamic_plugins): +def test_betxt_7bit(topology_st): """Test that the 7-bit plugin correctly rejects an invalid update :id: 9e2ab27b-eda9-4cd9-9968-a1a8513210fd @@ -51,55 +45,39 @@ def test_betxt_7bit(topology_st, dynamic_plugins): log.info('Running test_betxt_7bit...') - USER_DN = 'uid=test_entry,' + DEFAULT_SUFFIX - eight_bit_rdn = six.u('uid=Fu\u00c4\u00e8') - BAD_RDN = eight_bit_rdn.encode('utf-8') + BAD_RDN = u'uid=Fu\u00c4\u00e8' - # This plugin should on by default, but just in case... - topology_st.standalone.plugins.enable(name=PLUGIN_7_BIT_CHECK) + sevenbc = SevenBitCheckPlugin(topology_st.standalone) + sevenbc.enable() + topology_st.standalone.restart() - # Add our test user - try: - topology_st.standalone.add_s(Entry((USER_DN, {'objectclass': "top extensibleObject".split(), - 'sn': '1', - 'cn': 'test 1', - 'uid': 'test_entry', - 'userpassword': 'password'}))) - except ldap.LDAPError as e: - log.error('Failed to add test user' + USER_DN + ': error ' + e.message['desc']) - assert False + + users = UserAccounts(topology_st.standalone, basedn=DEFAULT_SUFFIX) + user = users.create(properties=TEST_USER_PROPERTIES) # Attempt a modrdn, this should fail + try: - topology_st.standalone.rename_s(USER_DN, BAD_RDN, delold=0) + user.rename(BAD_RDN) log.fatal('test_betxt_7bit: Modrdn operation incorrectly succeeded') assert False except ldap.LDAPError as e: - log.info('Modrdn failed as expected: error ' + e.message['desc']) + log.info('Modrdn failed as expected: error %s' % str(e)) # Make sure the operation did not succeed, attempt to search for the new RDN - try: - entries = topology_st.standalone.search_s(DEFAULT_SUFFIX, ldap.SCOPE_SUBTREE, BAD_RDN) - if entries: - log.fatal('test_betxt_7bit: Incorrectly found the entry using the invalid RDN') - assert False - except ldap.LDAPError as e: - log.fatal('Error while searching for test entry: ' + e.message['desc']) - assert False + + user_check = users.get("testuser") + + assert user_check.dn == user.dn # # Cleanup - remove the user # - try: - topology_st.standalone.delete_s(USER_DN) - except ldap.LDAPError as e: - log.fatal('Failed to delete test entry: ' + e.message['desc']) - assert False - + user.delete() log.info('test_betxt_7bit: PASSED') -def test_betxn_attr_uniqueness(topology_st, dynamic_plugins): +def test_betxn_attr_uniqueness(topology_st): """Test that we can not add two entries that have the same attr value that is defined by the plugin @@ -124,50 +102,40 @@ def test_betxn_attr_uniqueness(topology_st, dynamic_plugins): USER1_DN = 'uid=test_entry1,' + DEFAULT_SUFFIX USER2_DN = 'uid=test_entry2,' + DEFAULT_SUFFIX - topology_st.standalone.plugins.enable(name=PLUGIN_ATTR_UNIQUENESS) + attruniq = AttributeUniquenessPlugin(topology_st.standalone) + attruniq.enable() + topology_st.standalone.restart() - # Add the first entry - try: - topology_st.standalone.add_s(Entry((USER1_DN, {'objectclass': "top extensibleObject".split(), - 'sn': '1', - 'cn': 'test 1', - 'uid': 'test_entry1', - 'userpassword': 'password1'}))) - except ldap.LDAPError as e: - log.fatal('test_betxn_attr_uniqueness: Failed to add test user: ' + - USER1_DN + ', error ' + e.message['desc']) - assert False + users = UserAccounts(topology_st.standalone, basedn=DEFAULT_SUFFIX) + user1 = users.create(properties={ + 'uid': 'testuser1', + 'cn' : 'testuser1', + 'sn' : 'user1', + 'uidNumber' : '1001', + 'gidNumber' : '2001', + 'homeDirectory' : '/home/testuser1' + }) - # Add the second entry with a duplicate uid try: - topology_st.standalone.add_s(Entry((USER2_DN, {'objectclass': "top extensibleObject".split(), - 'sn': '2', - 'cn': 'test 2', - 'uid': 'test_entry2', - 'uid': 'test_entry1', # Duplicate value - 'userpassword': 'password2'}))) + user2 = users.create(properties={ + 'uid': ['testuser2', 'testuser1'], + 'cn' : 'testuser2', + 'sn' : 'user2', + 'uidNumber' : '1002', + 'gidNumber' : '2002', + 'homeDirectory' : '/home/testuser2' + }) log.fatal('test_betxn_attr_uniqueness: The second entry was incorrectly added.') assert False except ldap.LDAPError as e: - log.error('test_betxn_attr_uniqueness: Failed to add test user as expected: ' + - USER1_DN + ', error ' + e.message['desc']) + log.error('test_betxn_attr_uniqueness: Failed to add test user as expected:') - # - # Cleanup - disable plugin, remove test entry - # - topology_st.standalone.plugins.disable(name=PLUGIN_ATTR_UNIQUENESS) - - try: - topology_st.standalone.delete_s(USER1_DN) - except ldap.LDAPError as e: - log.fatal('test_betxn_attr_uniqueness: Failed to delete test entry1: ' + - e.message['desc']) - assert False + user1.delete() log.info('test_betxn_attr_uniqueness: PASSED') -def test_betxn_memberof(topology_st, dynamic_plugins): +def test_betxn_memberof(topology_st): """Test PLUGIN_MEMBER_OF plugin :id: 70d0b96e-b693-4bf7-bbf5-102a66ac5993 @@ -192,55 +160,34 @@ def test_betxn_memberof(topology_st, dynamic_plugins): ENTRY2_DN = 'cn=group2,' + DEFAULT_SUFFIX PLUGIN_DN = 'cn=' + PLUGIN_MEMBER_OF + ',cn=plugins,cn=config' - # Enable and configure memberOf plugin - topology_st.standalone.plugins.enable(name=PLUGIN_MEMBER_OF) - try: - topology_st.standalone.modify_s(PLUGIN_DN, [(ldap.MOD_REPLACE, 'memberofgroupattr', 'member'), - (ldap.MOD_REPLACE, 'memberofAutoAddOC', 'referral')]) - except ldap.LDAPError as e: - log.fatal('test_betxn_memberof: Failed to update config(member): error ' + e.message['desc']) - assert False + memberof = MemberOfPlugin(topology_st.standalone) + memberof.enable() + memberof.set_autoaddoc('referral') + # memberof.add_groupattr('member') # This is already the default. + topology_st.standalone.restart() - # Add our test entries - try: - topology_st.standalone.add_s(Entry((ENTRY1_DN, {'objectclass': "top groupofnames".split(), - 'cn': 'group1'}))) - except ldap.LDAPError as e: - log.error('test_betxn_memberof: Failed to add group1:' + - ENTRY1_DN + ', error ' + e.message['desc']) - assert False + groups = Groups(topology_st.standalone, DEFAULT_SUFFIX) + group1 = groups.create(properties={ + 'cn' : 'group1', + }) - try: - topology_st.standalone.add_s(Entry((ENTRY2_DN, {'objectclass': "top groupofnames".split(), - 'cn': 'group1'}))) - except ldap.LDAPError as e: - log.error('test_betxn_memberof: Failed to add group2:' + - ENTRY2_DN + ', error ' + e.message['desc']) - assert False - - # - # Test mod replace - # - - # Add group2 to group1 - it should fail with objectclass violation - try: - topology_st.standalone.modify_s(ENTRY1_DN, [(ldap.MOD_REPLACE, 'member', ENTRY2_DN)]) - log.fatal('test_betxn_memberof: Group2 was incorrectly allowed to be added to group1') - assert False - except ldap.LDAPError as e: - log.info('test_betxn_memberof: Group2 was correctly rejected (mod replace): error ' + e.message['desc']) + group2 = groups.create(properties={ + 'cn' : 'group2', + }) - # - # Test mod add - # + # We may need to mod groups to not have nsMemberOf ... ? + if not ds_is_older('1.3.7'): + group1.remove('objectClass', 'nsMemberOf') + group2.remove('objectClass', 'nsMemberOf') # Add group2 to group1 - it should fail with objectclass violation try: + group1.add_member(group2.dn) topology_st.standalone.modify_s(ENTRY1_DN, [(ldap.MOD_ADD, 'member', ENTRY2_DN)]) log.fatal('test_betxn_memberof: Group2 was incorrectly allowed to be added to group1') assert False except ldap.LDAPError as e: - log.info('test_betxn_memberof: Group2 was correctly rejected (mod add): error ' + e.message['desc']) + log.info('test_betxn_memberof: Group2 was correctly rejected (mod add): error') # # Done diff --git a/src/lib389/lib389/_mapped_object.py b/src/lib389/lib389/_mapped_object.py index f73cb25..0c63a2c 100644 --- a/src/lib389/lib389/_mapped_object.py +++ b/src/lib389/lib389/_mapped_object.py @@ -538,6 +538,37 @@ class DSLdapObject(DSLogging): conn.simple_bind_s(self.dn, password) return conn + # Modifies the DN of an entry to the new fqdn provided + def rename(self, new_rdn, newsuperior=None): + """Renames the object within the tree. + + If you provide a newsuperior, this will move the object in the tree. + If you only provide a new_rdn, it stays in the same branch, but just + changes the rdn. + + Note, if you use newsuperior, you may move this object outside of the + scope of the related DSLdapObjects manager, which may cause it not to + appear in .get() requests. + """ + # When we are finished with this, we need to update our DN + # To do this, we probably need to search the new rdn as a filter, + # and the superior as the base (if it changed) + if self._protected: + return + self._instance.rename_s(self._dn, new_rdn, newsuperior, serverctrls=self._server_controls, clientctrls=self._client_controls) + search_base = self._basedn + if newsuperior != None: + # Well, the new DN should be rdn + newsuperior. + self._dn = '%s,%s' % (new_rdn, newsuperior) + else: + old_dn_parts = ldap.explode_dn(self._dn) + # Replace the rdn + old_dn_parts[0] = new_rdn + self._dn = ",".join(old_dn_parts) + assert self.exists() + + # assert we actually got the change right .... + def delete(self): """Deletes the object defined by self._dn. This can be changed with the self._protected flag! -- 1.8.3.1