From 8c347e6135cebf4a93c0659915182d7f49472a82 Mon Sep 17 00:00:00 2001
From: William Brown <firstyear@redhat.com>
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           |  21 +++
 2 files changed, 84 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..c43576f 100644
--- a/src/lib389/lib389/_mapped_object.py
+++ b/src/lib389/lib389/_mapped_object.py
@@ -538,6 +538,27 @@ 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):
+        # 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

