From 60339ce804b74408fc2de0b4289a62fff5b79903 Mon Sep 17 00:00:00 2001
From: Akshay Adhikari <aadhikar@redhat.com>
Date: Jun 13 2018 10:55:35 +0000
Subject: Issue 49588 - Add py3 support for tickets : part-2


Description: Added py3 support by explicitly changing strings to bytes.
Ported tests from ticket to test suites, also added docstrings.

https://pagure.io/389-ds-base/issue/49588

Reviewed by: spichugi (Thanks!)

---

diff --git a/dirsrvtests/tests/suites/acl/repeated_ldap_add_test.py b/dirsrvtests/tests/suites/acl/repeated_ldap_add_test.py
new file mode 100644
index 0000000..9225f8f
--- /dev/null
+++ b/dirsrvtests/tests/suites/acl/repeated_ldap_add_test.py
@@ -0,0 +1,487 @@
+# --- BEGIN COPYRIGHT BLOCK ---
+# Copyright (C) 2016 Red Hat, Inc.
+# All rights reserved.
+#
+# License: GPL (version 3 or any later version).
+# See LICENSE for details.
+# --- END COPYRIGHT BLOCK ---
+#
+from subprocess import Popen
+
+import pytest
+from lib389.paths import Paths
+from lib389.tasks import *
+from lib389.utils import *
+from lib389.topologies import topology_st
+
+from lib389._constants import DN_DM, DEFAULT_SUFFIX, PASSWORD, SERVERID_STANDALONE
+
+logging.getLogger(__name__).setLevel(logging.DEBUG)
+log = logging.getLogger(__name__)
+
+CONFIG_DN = 'cn=config'
+BOU = 'BOU'
+BINDOU = 'ou=%s,%s' % (BOU, DEFAULT_SUFFIX)
+BUID = 'buser123'
+TUID = 'tuser0'
+BINDDN = 'uid=%s,%s' % (BUID, BINDOU)
+BINDPW = BUID
+TESTDN = 'uid=%s,ou=people,%s' % (TUID, DEFAULT_SUFFIX)
+TESTPW = TUID
+BOGUSDN = 'uid=bogus,%s' % DEFAULT_SUFFIX
+BOGUSDN2 = 'uid=bogus,ou=people,%s' % DEFAULT_SUFFIX
+BOGUSSUFFIX = 'uid=bogus,ou=people,dc=bogus'
+GROUPOU = 'ou=groups,%s' % DEFAULT_SUFFIX
+BOGUSOU = 'ou=OU,%s' % DEFAULT_SUFFIX
+
+def get_ldap_error_msg(e, type):
+    return e.args[0][type]
+
+def pattern_accesslog(file, log_pattern):
+    for i in range(5):
+        try:
+            pattern_accesslog.last_pos += 1
+        except AttributeError:
+            pattern_accesslog.last_pos = 0
+
+        found = None
+        file.seek(pattern_accesslog.last_pos)
+
+        # Use a while true iteration because 'for line in file: hit a
+        # python bug that break file.tell()
+        while True:
+            line = file.readline()
+            found = log_pattern.search(line)
+            if ((line == '') or (found)):
+                break
+
+        pattern_accesslog.last_pos = file.tell()
+        if found:
+            return line
+        else:
+            time.sleep(1)
+    return None
+
+
+def check_op_result(server, op, dn, superior, exists, rc):
+    targetdn = dn
+    if op == 'search':
+        if exists:
+            opstr = 'Searching existing entry'
+        else:
+            opstr = 'Searching non-existing entry'
+    elif op == 'add':
+        if exists:
+            opstr = 'Adding existing entry'
+        else:
+            opstr = 'Adding non-existing entry'
+    elif op == 'modify':
+        if exists:
+            opstr = 'Modifying existing entry'
+        else:
+            opstr = 'Modifying non-existing entry'
+    elif op == 'modrdn':
+        if superior is not None:
+            targetdn = superior
+            if exists:
+                opstr = 'Moving to existing superior'
+            else:
+                opstr = 'Moving to non-existing superior'
+        else:
+            if exists:
+                opstr = 'Renaming existing entry'
+            else:
+                opstr = 'Renaming non-existing entry'
+    elif op == 'delete':
+        if exists:
+            opstr = 'Deleting existing entry'
+        else:
+            opstr = 'Deleting non-existing entry'
+
+    if ldap.SUCCESS == rc:
+        expstr = 'be ok'
+    else:
+        expstr = 'fail with %s' % rc.__name__
+
+    log.info('%s %s, which should %s.' % (opstr, targetdn, expstr))
+    time.sleep(1)
+    hit = 0
+    try:
+        if op == 'search':
+            centry = server.search_s(dn, ldap.SCOPE_BASE, 'objectclass=*')
+        elif op == 'add':
+            server.add_s(Entry((dn, {'objectclass': 'top extensibleObject'.split(),
+                                     'cn': 'test entry'})))
+        elif op == 'modify':
+            server.modify_s(dn, [(ldap.MOD_REPLACE, 'description', b'test')])
+        elif op == 'modrdn':
+            if superior is not None:
+                server.rename_s(dn, 'uid=new', newsuperior=superior, delold=1)
+            else:
+                server.rename_s(dn, 'uid=new', delold=1)
+        elif op == 'delete':
+            server.delete_s(dn)
+        else:
+            log.fatal('Unknown operation %s' % op)
+            assert False
+    except ldap.LDAPError as e:
+        hit = 1
+        log.info("Exception (expected): %s" % type(e).__name__)
+        log.info('Desc {}'.format(get_ldap_error_msg(e,'desc')))
+        assert isinstance(e, rc)
+        if 'matched' in e.args:
+            log.info('Matched is returned: {}'.format(get_ldap_error_msg(e, 'matched')))
+            if rc != ldap.NO_SUCH_OBJECT:
+                assert False
+
+    if ldap.SUCCESS == rc:
+        if op == 'search':
+            log.info('Search should return none')
+            assert len(centry) == 0
+    else:
+        if 0 == hit:
+            log.info('Expected to fail with %s, but passed' % rc.__name__)
+            assert False
+
+    log.info('PASSED\n')
+
+
+@pytest.mark.bz1347760
+def test_repeated_ldap_add(topology_st):
+    """Prevent revealing the entry info to whom has no access rights.
+
+    :id: 76d278bd-3e51-4579-951a-753e6703b4df
+    :setup: Standalone instance
+    :steps:
+        1.  Disable accesslog logbuffering
+        2.  Bind as "cn=Directory Manager"
+        3.  Add a organisational unit as BOU
+        4.  Add a bind user as uid=buser123,ou=BOU,dc=example,dc=com
+        5.  Add a test user as uid=tuser0,ou=People,dc=example,dc=com
+        6.  Delete aci in dc=example,dc=com
+        7.  Bind as Directory Manager, acquire an access log path and instance dir
+        8.  Bind as uid=buser123,ou=BOU,dc=example,dc=com who has no right to read the entry
+        9.  Bind as uid=bogus,ou=people,dc=bogus,bogus who does not exist
+        10. Bind as uid=buser123,ou=BOU,dc=example,dc=com,bogus with wrong password
+        11. Adding aci for uid=buser123,ou=BOU,dc=example,dc=com to ou=BOU,dc=example,dc=com.
+        12. Bind as uid=buser123,ou=BOU,dc=example,dc=com now who has right to read the entry
+    :expectedresults:
+        1.  Operation should be successful
+        2.  Operation should be successful
+        3.  Operation should be successful
+        4.  Operation should be successful
+        5.  Operation should be successful
+        6.  Operation should be successful
+        7.  Operation should be successful
+        8.  Bind operation should be successful with no search result
+        9.  Bind operation should Fail
+        10. Bind operation should Fail
+        11. Operation should be successful
+        12. Bind operation should be successful with search result
+    """
+    log.info('Testing Bug 1347760 - Information disclosure via repeated use of LDAP ADD operation, etc.')
+
+    log.info('Disabling accesslog logbuffering')
+    topology_st.standalone.modify_s(CONFIG_DN, [(ldap.MOD_REPLACE, 'nsslapd-accesslog-logbuffering', b'off')])
+
+    log.info('Bind as {%s,%s}' % (DN_DM, PASSWORD))
+    topology_st.standalone.simple_bind_s(DN_DM, PASSWORD)
+
+    log.info('Adding ou=%s a bind user belongs to.' % BOU)
+    topology_st.standalone.add_s(Entry((BINDOU, {
+        'objectclass': 'top organizationalunit'.split(),
+        'ou': BOU})))
+
+    log.info('Adding a bind user.')
+    topology_st.standalone.add_s(Entry((BINDDN,
+                                        {'objectclass': "top person organizationalPerson inetOrgPerson".split(),
+                                         'cn': 'bind user',
+                                         'sn': 'user',
+                                         'userPassword': BINDPW})))
+
+    log.info('Adding a test user.')
+    topology_st.standalone.add_s(Entry((TESTDN,
+                                        {'objectclass': "top person organizationalPerson inetOrgPerson".split(),
+                                         'cn': 'test user',
+                                         'sn': 'user',
+                                         'userPassword': TESTPW})))
+
+    log.info('Deleting aci in %s.' % DEFAULT_SUFFIX)
+    topology_st.standalone.modify_s(DEFAULT_SUFFIX, [(ldap.MOD_DELETE, 'aci', None)])
+
+    log.info('While binding as DM, acquire an access log path and instance dir')
+    ds_paths = Paths(serverid=topology_st.standalone.serverid,
+                     instance=topology_st.standalone)
+    file_path = ds_paths.access_log
+    inst_dir = ds_paths.inst_dir
+
+    log.info('Bind case 1. the bind user has no rights to read the entry itself, bind should be successful.')
+    log.info('Bind as {%s,%s} who has no access rights.' % (BINDDN, BINDPW))
+    try:
+        topology_st.standalone.simple_bind_s(BINDDN, BINDPW)
+    except ldap.LDAPError as e:
+        log.info('Desc {}'.format(get_ldap_error_msg(e,'desc')))
+        assert False
+
+    file_obj = open(file_path, "r")
+    log.info('Access log path: %s' % file_path)
+
+    log.info(
+        'Bind case 2-1. the bind user does not exist, bind should fail with error %s' % ldap.INVALID_CREDENTIALS.__name__)
+    log.info('Bind as {%s,%s} who does not exist.' % (BOGUSDN, 'bogus'))
+    try:
+        topology_st.standalone.simple_bind_s(BOGUSDN, 'bogus')
+    except ldap.LDAPError as e:
+        log.info("Exception (expected): %s" % type(e).__name__)
+        log.info('Desc {}'.format(get_ldap_error_msg(e,'desc')))
+        assert isinstance(e, ldap.INVALID_CREDENTIALS)
+        regex = re.compile('No such entry')
+        cause = pattern_accesslog(file_obj, regex)
+        if cause is None:
+            log.fatal('Cause not found - %s' % cause)
+            assert False
+        else:
+            log.info('Cause found - %s' % cause)
+    time.sleep(1)
+
+    log.info(
+        'Bind case 2-2. the bind user\'s suffix does not exist, bind should fail with error %s' % ldap.INVALID_CREDENTIALS.__name__)
+    log.info('Bind as {%s,%s} who does not exist.' % (BOGUSSUFFIX, 'bogus'))
+    with pytest.raises(ldap.INVALID_CREDENTIALS):
+        topology_st.standalone.simple_bind_s(BOGUSSUFFIX, 'bogus')
+    regex = re.compile('No suffix for bind')
+    cause = pattern_accesslog(file_obj, regex)
+    if cause is None:
+        log.fatal('Cause not found - %s' % cause)
+        assert False
+    else:
+        log.info('Cause found - %s' % cause)
+    time.sleep(1)
+
+    log.info(
+        'Bind case 2-3. the bind user\'s password is wrong, bind should fail with error %s' % ldap.INVALID_CREDENTIALS.__name__)
+    log.info('Bind as {%s,%s} who does not exist.' % (BINDDN, 'bogus'))
+    try:
+        topology_st.standalone.simple_bind_s(BINDDN, 'bogus')
+    except ldap.LDAPError as e:
+        log.info("Exception (expected): %s" % type(e).__name__)
+        log.info('Desc {}'.format(get_ldap_error_msg(e,'desc')))
+        assert isinstance(e, ldap.INVALID_CREDENTIALS)
+        regex = re.compile('Invalid credentials')
+        cause = pattern_accesslog(file_obj, regex)
+        if cause is None:
+            log.fatal('Cause not found - %s' % cause)
+            assert False
+        else:
+            log.info('Cause found - %s' % cause)
+    time.sleep(1)
+
+    log.info('Adding aci for %s to %s.' % (BINDDN, BINDOU))
+    acival = '(targetattr="*")(version 3.0; acl "%s"; allow(all) userdn = "ldap:///%s";)' % (BUID, BINDDN)
+    log.info('aci: %s' % acival)
+    log.info('Bind as {%s,%s}' % (DN_DM, PASSWORD))
+    topology_st.standalone.simple_bind_s(DN_DM, PASSWORD)
+    topology_st.standalone.modify_s(BINDOU, [(ldap.MOD_ADD, 'aci', ensure_bytes(acival))])
+    time.sleep(1)
+
+    log.info('Bind case 3. the bind user has the right to read the entry itself, bind should be successful.')
+    log.info('Bind as {%s,%s} which should be ok.\n' % (BINDDN, BINDPW))
+    topology_st.standalone.simple_bind_s(BINDDN, BINDPW)
+
+    log.info('The following operations are against the subtree the bind user %s has no rights.' % BINDDN)
+    # Search
+    exists = True
+    rc = ldap.SUCCESS
+    log.info(
+        'Search case 1. the bind user has no rights to read the search entry, it should return no search results with %s' % rc)
+    check_op_result(topology_st.standalone, 'search', TESTDN, None, exists, rc)
+
+    exists = False
+    rc = ldap.SUCCESS
+    log.info(
+        'Search case 2-1. the search entry does not exist, the search should return no search results with %s' % rc.__name__)
+    check_op_result(topology_st.standalone, 'search', BOGUSDN, None, exists, rc)
+
+    exists = False
+    rc = ldap.SUCCESS
+    log.info(
+        'Search case 2-2. the search entry does not exist, the search should return no search results with %s' % rc.__name__)
+    check_op_result(topology_st.standalone, 'search', BOGUSDN2, None, exists, rc)
+
+    # Add
+    exists = True
+    rc = ldap.INSUFFICIENT_ACCESS
+    log.info(
+        'Add case 1. the bind user has no rights AND the adding entry exists, it should fail with %s' % rc.__name__)
+    check_op_result(topology_st.standalone, 'add', TESTDN, None, exists, rc)
+
+    exists = False
+    rc = ldap.INSUFFICIENT_ACCESS
+    log.info(
+        'Add case 2-1. the bind user has no rights AND the adding entry does not exist, it should fail with %s' % rc.__name__)
+    check_op_result(topology_st.standalone, 'add', BOGUSDN, None, exists, rc)
+
+    exists = False
+    rc = ldap.INSUFFICIENT_ACCESS
+    log.info(
+        'Add case 2-2. the bind user has no rights AND the adding entry does not exist, it should fail with %s' % rc.__name__)
+    check_op_result(topology_st.standalone, 'add', BOGUSDN2, None, exists, rc)
+
+    # Modify
+    exists = True
+    rc = ldap.INSUFFICIENT_ACCESS
+    log.info(
+        'Modify case 1. the bind user has no rights AND the modifying entry exists, it should fail with %s' % rc.__name__)
+    check_op_result(topology_st.standalone, 'modify', TESTDN, None, exists, rc)
+
+    exists = False
+    rc = ldap.INSUFFICIENT_ACCESS
+    log.info(
+        'Modify case 2-1. the bind user has no rights AND the modifying entry does not exist, it should fail with %s' % rc.__name__)
+    check_op_result(topology_st.standalone, 'modify', BOGUSDN, None, exists, rc)
+
+    exists = False
+    rc = ldap.INSUFFICIENT_ACCESS
+    log.info(
+        'Modify case 2-2. the bind user has no rights AND the modifying entry does not exist, it should fail with %s' % rc.__name__)
+    check_op_result(topology_st.standalone, 'modify', BOGUSDN2, None, exists, rc)
+
+    # Modrdn
+    exists = True
+    rc = ldap.INSUFFICIENT_ACCESS
+    log.info(
+        'Modrdn case 1. the bind user has no rights AND the renaming entry exists, it should fail with %s' % rc.__name__)
+    check_op_result(topology_st.standalone, 'modrdn', TESTDN, None, exists, rc)
+
+    exists = False
+    rc = ldap.INSUFFICIENT_ACCESS
+    log.info(
+        'Modrdn case 2-1. the bind user has no rights AND the renaming entry does not exist, it should fail with %s' % rc.__name__)
+    check_op_result(topology_st.standalone, 'modrdn', BOGUSDN, None, exists, rc)
+
+    exists = False
+    rc = ldap.INSUFFICIENT_ACCESS
+    log.info(
+        'Modrdn case 2-2. the bind user has no rights AND the renaming entry does not exist, it should fail with %s' % rc.__name__)
+    check_op_result(topology_st.standalone, 'modrdn', BOGUSDN2, None, exists, rc)
+
+    exists = True
+    rc = ldap.INSUFFICIENT_ACCESS
+    log.info(
+        'Modrdn case 3. the bind user has no rights AND the node moving an entry to exists, it should fail with %s' % rc.__name__)
+    check_op_result(topology_st.standalone, 'modrdn', TESTDN, GROUPOU, exists, rc)
+
+    exists = False
+    rc = ldap.INSUFFICIENT_ACCESS
+    log.info(
+        'Modrdn case 4-1. the bind user has no rights AND the node moving an entry to does not, it should fail with %s' % rc.__name__)
+    check_op_result(topology_st.standalone, 'modrdn', TESTDN, BOGUSOU, exists, rc)
+
+    exists = False
+    rc = ldap.INSUFFICIENT_ACCESS
+    log.info(
+        'Modrdn case 4-2. the bind user has no rights AND the node moving an entry to does not, it should fail with %s' % rc.__name__)
+    check_op_result(topology_st.standalone, 'modrdn', TESTDN, BOGUSOU, exists, rc)
+
+    # Delete
+    exists = True
+    rc = ldap.INSUFFICIENT_ACCESS
+    log.info(
+        'Delete case 1. the bind user has no rights AND the deleting entry exists, it should fail with %s' % rc.__name__)
+    check_op_result(topology_st.standalone, 'delete', TESTDN, None, exists, rc)
+
+    exists = False
+    rc = ldap.INSUFFICIENT_ACCESS
+    log.info(
+        'Delete case 2-1. the bind user has no rights AND the deleting entry does not exist, it should fail with %s' % rc.__name__)
+    check_op_result(topology_st.standalone, 'delete', BOGUSDN, None, exists, rc)
+
+    exists = False
+    rc = ldap.INSUFFICIENT_ACCESS
+    log.info(
+        'Delete case 2-2. the bind user has no rights AND the deleting entry does not exist, it should fail with %s' % rc.__name__)
+    check_op_result(topology_st.standalone, 'delete', BOGUSDN2, None, exists, rc)
+
+    log.info('EXTRA: Check no regressions')
+    log.info('Adding aci for %s to %s.' % (BINDDN, DEFAULT_SUFFIX))
+    acival = '(targetattr="*")(version 3.0; acl "%s-all"; allow(all) userdn = "ldap:///%s";)' % (BUID, BINDDN)
+    log.info('Bind as {%s,%s}' % (DN_DM, PASSWORD))
+    topology_st.standalone.simple_bind_s(DN_DM, PASSWORD)
+    topology_st.standalone.modify_s(DEFAULT_SUFFIX, [(ldap.MOD_ADD, 'aci', ensure_bytes(acival))])
+    time.sleep(1)
+
+    log.info('Bind as {%s,%s}.' % (BINDDN, BINDPW))
+    try:
+        topology_st.standalone.simple_bind_s(BINDDN, BINDPW)
+    except ldap.LDAPError as e:
+        log.info('Desc {}'.format(get_ldap_error_msg(e,'desc')))
+        assert False
+    time.sleep(1)
+
+    exists = False
+    rc = ldap.NO_SUCH_OBJECT
+    log.info('Search case. the search entry does not exist, the search should fail with %s' % rc.__name__)
+    check_op_result(topology_st.standalone, 'search', BOGUSDN2, None, exists, rc)
+    file_obj.close()
+
+    exists = True
+    rc = ldap.ALREADY_EXISTS
+    log.info('Add case. the adding entry already exists, it should fail with %s' % rc.__name__)
+    check_op_result(topology_st.standalone, 'add', TESTDN, None, exists, rc)
+
+    exists = False
+    rc = ldap.NO_SUCH_OBJECT
+    log.info('Modify case. the modifying entry does not exist, it should fail with %s' % rc.__name__)
+    check_op_result(topology_st.standalone, 'modify', BOGUSDN, None, exists, rc)
+
+    exists = False
+    rc = ldap.NO_SUCH_OBJECT
+    log.info('Modrdn case 1. the renaming entry does not exist, it should fail with %s' % rc.__name__)
+    check_op_result(topology_st.standalone, 'modrdn', BOGUSDN, None, exists, rc)
+
+    exists = False
+    rc = ldap.NO_SUCH_OBJECT
+    log.info('Modrdn case 2. the node moving an entry to does not, it should fail with %s' % rc.__name__)
+    check_op_result(topology_st.standalone, 'modrdn', TESTDN, BOGUSOU, exists, rc)
+
+    exists = False
+    rc = ldap.NO_SUCH_OBJECT
+    log.info('Delete case. the deleting entry does not exist, it should fail with %s' % rc.__name__)
+    check_op_result(topology_st.standalone, 'delete', BOGUSDN, None, exists, rc)
+
+    log.info('Inactivate %s' % BINDDN)
+    if ds_paths.version < '1.3':
+        nsinactivate = '%s/ns-inactivate.pl' % inst_dir
+        nsinactivate_cmd = [nsinactivate, '-D', DN_DM, '-w', PASSWORD, '-I', BINDDN]
+    else:
+        nsinactivate = '%s/ns-inactivate.pl' % ds_paths.sbin_dir
+        nsinactivate_cmd = [nsinactivate, '-Z', SERVERID_STANDALONE, '-D', DN_DM, '-w', PASSWORD, '-I', BINDDN]
+    log.info(nsinactivate_cmd)
+    p = Popen(nsinactivate_cmd)
+    assert (p.wait() == 0)
+
+    log.info('Bind as {%s,%s} which should fail with %s.' % (BINDDN, BUID, ldap.UNWILLING_TO_PERFORM.__name__))
+    try:
+        topology_st.standalone.simple_bind_s(BINDDN, BUID)
+    except ldap.LDAPError as e:
+        log.info("Exception (expected): %s" % type(e).__name__)
+        log.info('Desc {}'.format(get_ldap_error_msg(e,'desc')))
+        assert isinstance(e, ldap.UNWILLING_TO_PERFORM)
+
+    log.info('Bind as {%s,%s} which should fail with %s.' % (BINDDN, 'bogus', ldap.UNWILLING_TO_PERFORM.__name__))
+    try:
+        topology_st.standalone.simple_bind_s(BINDDN, 'bogus')
+    except ldap.LDAPError as e:
+        log.info("Exception (expected): %s" % type(e).__name__)
+        log.info('Desc {}'.format(get_ldap_error_msg(e,'desc')))
+        assert isinstance(e, ldap.UNWILLING_TO_PERFORM)
+
+    log.info('SUCCESS')
+
+
+if __name__ == '__main__':
+    # Run isolated
+    # -s for DEBUG mode
+    CURRENT_FILE = os.path.realpath(__file__)
+    pytest.main("-s %s" % CURRENT_FILE)
+
diff --git a/dirsrvtests/tests/suites/acl/selfdn_permissions_test.py b/dirsrvtests/tests/suites/acl/selfdn_permissions_test.py
new file mode 100644
index 0000000..6858ca7
--- /dev/null
+++ b/dirsrvtests/tests/suites/acl/selfdn_permissions_test.py
@@ -0,0 +1,351 @@
+# --- BEGIN COPYRIGHT BLOCK ---
+# Copyright (C) 2016 Red Hat, Inc.
+# All rights reserved.
+#
+# License: GPL (version 3 or any later version).
+# See LICENSE for details.
+# --- END COPYRIGHT BLOCK ---
+#
+import logging
+
+import ldap
+import pytest
+from lib389 import Entry
+from lib389._constants import *
+from lib389.topologies import topology_st
+
+log = logging.getLogger(__name__)
+
+from lib389.utils import *
+
+# Skip on older versions
+pytestmark = pytest.mark.skipif(ds_is_older('1.3.2'), reason="Not implemented")
+OC_NAME = 'OCticket47653'
+MUST = "(postalAddress $ postalCode)"
+MAY = "(member $ street)"
+
+OTHER_NAME = 'other_entry'
+MAX_OTHERS = 10
+
+BIND_NAME = 'bind_entry'
+BIND_DN = 'cn=%s, %s' % (BIND_NAME, SUFFIX)
+BIND_PW = 'password'
+
+ENTRY_NAME = 'test_entry'
+ENTRY_DN = 'cn=%s, %s' % (ENTRY_NAME, SUFFIX)
+ENTRY_OC = "top person %s" % OC_NAME
+
+
+def _oc_definition(oid_ext, name, must=None, may=None):
+    oid = "1.2.3.4.5.6.7.8.9.10.%d" % oid_ext
+    desc = 'To test ticket 47490'
+    sup = 'person'
+    if not must:
+        must = MUST
+    if not may:
+        may = MAY
+
+    new_oc = "( %s  NAME '%s' DESC '%s' SUP %s AUXILIARY MUST %s MAY %s )" % (oid, name, desc, sup, must, may)
+    return ensure_bytes(new_oc)
+
+
+@pytest.fixture(scope="module")
+def allow_user_init(topology_st):
+    """Initialize the test environment
+
+     """
+    topology_st.standalone.log.info("Add %s that allows 'member' attribute" % OC_NAME)
+    new_oc = _oc_definition(2, OC_NAME, must=MUST, may=MAY)
+    topology_st.standalone.schema.add_schema('objectClasses', new_oc)
+
+    # entry used to bind with
+    topology_st.standalone.log.info("Add %s" % BIND_DN)
+    topology_st.standalone.add_s(Entry((BIND_DN, {
+        'objectclass': "top person".split(),
+        'sn': BIND_NAME,
+        'cn': BIND_NAME,
+        'userpassword': BIND_PW})))
+
+    # enable acl error logging
+    mod = [(ldap.MOD_REPLACE, 'nsslapd-errorlog-level', b'128')]
+    topology_st.standalone.modify_s(DN_CONFIG, mod)
+
+    # Remove aci's to start with a clean slate
+    mod = [(ldap.MOD_DELETE, 'aci', None)]
+    topology_st.standalone.modify_s(SUFFIX, mod)
+
+    # add dummy entries
+    for cpt in range(MAX_OTHERS):
+        name = "%s%d" % (OTHER_NAME, cpt)
+        topology_st.standalone.add_s(Entry(("cn=%s,%s" % (name, SUFFIX), {
+            'objectclass': "top person".split(),
+            'sn': name,
+            'cn': name})))
+
+
+@pytest.mark.ds47653
+def test_selfdn_permission_add(topology_st, allow_user_init):
+    """Check add entry operation with and without SelfDN aci
+
+    :id: e837a9ef-be92-48da-ad8b-ebf42b0fede1
+    :setup: Standalone instance, add a entry which is used to bind,
+    enable acl error logging by setting 'nsslapd-errorlog-level' to '128',
+    remove aci's to start with a clean slate, and add dummy entries
+    :steps:
+        1. Check we can not ADD an entry without the proper SELFDN aci
+        2. Check with the proper ACI we can not ADD with 'member' attribute
+        3. Check entry to add with memberS and with the ACI
+        4. Check with the proper ACI and 'member' it succeeds to ADD
+    :expectedresults:
+        1. Operation should be successful
+        2. Operation should be successful
+        3. Operation should fail with Insufficient Access
+        4. Operation should be successful
+     """
+    topology_st.standalone.log.info("\n\n######################### ADD ######################\n")
+
+    # bind as bind_entry
+    topology_st.standalone.log.info("Bind as %s" % BIND_DN)
+    topology_st.standalone.simple_bind_s(BIND_DN, BIND_PW)
+
+    # Prepare the entry with multivalued members
+    entry_with_members = Entry(ENTRY_DN)
+    entry_with_members.setValues('objectclass', 'top', 'person', 'OCticket47653')
+    entry_with_members.setValues('sn', ENTRY_NAME)
+    entry_with_members.setValues('cn', ENTRY_NAME)
+    entry_with_members.setValues('postalAddress', 'here')
+    entry_with_members.setValues('postalCode', '1234')
+    members = []
+    for cpt in range(MAX_OTHERS):
+        name = "%s%d" % (OTHER_NAME, cpt)
+        members.append("cn=%s,%s" % (name, SUFFIX))
+    members.append(BIND_DN)
+    entry_with_members.setValues('member', members)
+
+    # Prepare the entry with one member
+    entry_with_member = Entry(ENTRY_DN)
+    entry_with_member.setValues('objectclass', 'top', 'person', 'OCticket47653')
+    entry_with_member.setValues('sn', ENTRY_NAME)
+    entry_with_member.setValues('cn', ENTRY_NAME)
+    entry_with_member.setValues('postalAddress', 'here')
+    entry_with_member.setValues('postalCode', '1234')
+    member = []
+    member.append(BIND_DN)
+    entry_with_member.setValues('member', member)
+
+    # entry to add WITH member being BIND_DN but WITHOUT the ACI -> ldap.INSUFFICIENT_ACCESS
+    try:
+        topology_st.standalone.log.info("Try to add Add  %s (aci is missing): %r" % (ENTRY_DN, entry_with_member))
+
+        topology_st.standalone.add_s(entry_with_member)
+    except Exception as e:
+        topology_st.standalone.log.info("Exception (expected): %s" % type(e).__name__)
+        assert isinstance(e, ldap.INSUFFICIENT_ACCESS)
+
+    # Ok Now add the proper ACI
+    topology_st.standalone.log.info("Bind as %s and add the ADD SELFDN aci" % DN_DM)
+    topology_st.standalone.simple_bind_s(DN_DM, PASSWORD)
+
+    ACI_TARGET = "(target = \"ldap:///cn=*,%s\")" % SUFFIX
+    ACI_TARGETFILTER = "(targetfilter =\"(objectClass=%s)\")" % OC_NAME
+    ACI_ALLOW = "(version 3.0; acl \"SelfDN add\"; allow (add)"
+    ACI_SUBJECT = " userattr = \"member#selfDN\";)"
+    ACI_BODY = ACI_TARGET + ACI_TARGETFILTER + ACI_ALLOW + ACI_SUBJECT
+    mod = [(ldap.MOD_ADD, 'aci', ensure_bytes(ACI_BODY))]
+    topology_st.standalone.modify_s(SUFFIX, mod)
+
+    # bind as bind_entry
+    topology_st.standalone.log.info("Bind as %s" % BIND_DN)
+    topology_st.standalone.simple_bind_s(BIND_DN, BIND_PW)
+
+    # entry to add WITHOUT member and WITH the ACI -> ldap.INSUFFICIENT_ACCESS
+    try:
+        topology_st.standalone.log.info("Try to add Add  %s (member is missing)" % ENTRY_DN)
+        topology_st.standalone.add_s(Entry((ENTRY_DN, {
+            'objectclass': ENTRY_OC.split(),
+            'sn': ENTRY_NAME,
+            'cn': ENTRY_NAME,
+            'postalAddress': 'here',
+            'postalCode': '1234'})))
+    except Exception as e:
+        topology_st.standalone.log.info("Exception (expected): %s" % type(e).__name__)
+        assert isinstance(e, ldap.INSUFFICIENT_ACCESS)
+
+    # entry to add WITH memberS and WITH the ACI -> ldap.INSUFFICIENT_ACCESS
+    # member should contain only one value
+    try:
+        topology_st.standalone.log.info("Try to add Add  %s (with several member values)" % ENTRY_DN)
+        topology_st.standalone.add_s(entry_with_members)
+    except Exception as e:
+        topology_st.standalone.log.info("Exception (expected): %s" % type(e).__name__)
+        assert isinstance(e, ldap.INSUFFICIENT_ACCESS)
+
+    topology_st.standalone.log.info("Try to add Add  %s should be successful" % ENTRY_DN)
+    topology_st.standalone.add_s(entry_with_member)
+
+
+@pytest.mark.ds47653
+def test_selfdn_permission_search(topology_st, allow_user_init):
+    """Check search operation with and without SelfDN aci
+
+    :id: 06d51ef9-c675-4583-99b2-4852dbda190e
+    :setup: Standalone instance, add a entry which is used to bind,
+    enable acl error logging by setting 'nsslapd-errorlog-level' to '128',
+    remove aci's to start with a clean slate, and add dummy entries
+    :steps:
+        1. Check we can not search an entry without the proper SELFDN aci
+        2. Add proper ACI
+        3. Check we can search with the proper ACI
+    :expectedresults:
+        1. Operation should be successful
+        2. Operation should be successful
+        3. Operation should be successful
+     """
+    topology_st.standalone.log.info("\n\n######################### SEARCH ######################\n")
+    # bind as bind_entry
+    topology_st.standalone.log.info("Bind as %s" % BIND_DN)
+    topology_st.standalone.simple_bind_s(BIND_DN, BIND_PW)
+
+    # entry to search WITH member being BIND_DN but WITHOUT the ACI -> no entry returned
+    topology_st.standalone.log.info("Try to search  %s (aci is missing)" % ENTRY_DN)
+    ents = topology_st.standalone.search_s(ENTRY_DN, ldap.SCOPE_BASE, 'objectclass=*')
+    assert len(ents) == 0
+
+    # Ok Now add the proper ACI
+    topology_st.standalone.log.info("Bind as %s and add the READ/SEARCH SELFDN aci" % DN_DM)
+    topology_st.standalone.simple_bind_s(DN_DM, PASSWORD)
+
+    ACI_TARGET = "(target = \"ldap:///cn=*,%s\")" % SUFFIX
+    ACI_TARGETATTR = "(targetattr = *)"
+    ACI_TARGETFILTER = "(targetfilter =\"(objectClass=%s)\")" % OC_NAME
+    ACI_ALLOW = "(version 3.0; acl \"SelfDN search-read\"; allow (read, search, compare)"
+    ACI_SUBJECT = " userattr = \"member#selfDN\";)"
+    ACI_BODY = ACI_TARGET + ACI_TARGETATTR + ACI_TARGETFILTER + ACI_ALLOW + ACI_SUBJECT
+    mod = [(ldap.MOD_ADD, 'aci', ensure_bytes(ACI_BODY))]
+    topology_st.standalone.modify_s(SUFFIX, mod)
+
+    # bind as bind_entry
+    topology_st.standalone.log.info("Bind as %s" % BIND_DN)
+    topology_st.standalone.simple_bind_s(BIND_DN, BIND_PW)
+
+    # entry to search with the proper aci
+    topology_st.standalone.log.info("Try to search  %s should be successful" % ENTRY_DN)
+    ents = topology_st.standalone.search_s(ENTRY_DN, ldap.SCOPE_BASE, 'objectclass=*')
+    assert len(ents) == 1
+
+
+@pytest.mark.ds47653
+def test_selfdn_permission_modify(topology_st, allow_user_init):
+    """Check modify operation with and without SelfDN aci
+
+    :id: 97a58844-095f-44b0-9029-dd29a7d83d68
+    :setup: Standalone instance, add a entry which is used to bind,
+    enable acl error logging by setting 'nsslapd-errorlog-level' to '128',
+    remove aci's to start with a clean slate, and add dummy entries
+    :steps:
+        1. Check we can not modify an entry without the proper SELFDN aci
+        2. Add proper ACI
+        3. Modify the entry and check the modified value
+    :expectedresults:
+        1. Operation should be successful
+        2. Operation should be successful
+        3. Operation should be successful
+     """
+    # bind as bind_entry
+    topology_st.standalone.log.info("Bind as %s" % BIND_DN)
+    topology_st.standalone.simple_bind_s(BIND_DN, BIND_PW)
+
+    topology_st.standalone.log.info("\n\n######################### MODIFY ######################\n")
+
+    # entry to modify WITH member being BIND_DN but WITHOUT the ACI -> ldap.INSUFFICIENT_ACCESS
+    try:
+        topology_st.standalone.log.info("Try to modify  %s (aci is missing)" % ENTRY_DN)
+        mod = [(ldap.MOD_REPLACE, 'postalCode', b'9876')]
+        topology_st.standalone.modify_s(ENTRY_DN, mod)
+    except Exception as e:
+        topology_st.standalone.log.info("Exception (expected): %s" % type(e).__name__)
+        assert isinstance(e, ldap.INSUFFICIENT_ACCESS)
+
+    # Ok Now add the proper ACI
+    topology_st.standalone.log.info("Bind as %s and add the WRITE SELFDN aci" % DN_DM)
+    topology_st.standalone.simple_bind_s(DN_DM, PASSWORD)
+
+    ACI_TARGET = "(target = \"ldap:///cn=*,%s\")" % SUFFIX
+    ACI_TARGETATTR = "(targetattr = *)"
+    ACI_TARGETFILTER = "(targetfilter =\"(objectClass=%s)\")" % OC_NAME
+    ACI_ALLOW = "(version 3.0; acl \"SelfDN write\"; allow (write)"
+    ACI_SUBJECT = " userattr = \"member#selfDN\";)"
+    ACI_BODY = ACI_TARGET + ACI_TARGETATTR + ACI_TARGETFILTER + ACI_ALLOW + ACI_SUBJECT
+    mod = [(ldap.MOD_ADD, 'aci', ensure_bytes(ACI_BODY))]
+    topology_st.standalone.modify_s(SUFFIX, mod)
+
+    # bind as bind_entry
+    topology_st.standalone.log.info("Bind as %s" % BIND_DN)
+    topology_st.standalone.simple_bind_s(BIND_DN, BIND_PW)
+
+    # modify the entry and checks the value
+    topology_st.standalone.log.info("Try to modify  %s. It should succeeds" % ENTRY_DN)
+    mod = [(ldap.MOD_REPLACE, 'postalCode', b'1928')]
+    topology_st.standalone.modify_s(ENTRY_DN, mod)
+
+    ents = topology_st.standalone.search_s(ENTRY_DN, ldap.SCOPE_BASE, 'objectclass=*')
+    assert len(ents) == 1
+    assert ensure_str(ents[0].postalCode) == '1928'
+
+
+@pytest.mark.ds47653
+def test_selfdn_permission_delete(topology_st, allow_user_init):
+    """Check delete operation with and without SelfDN aci
+
+    :id: 0ec4c0ec-e7b0-4ef1-8373-ab25aae34516
+    :setup: Standalone instance, add a entry which is used to bind,
+    enable acl error logging by setting 'nsslapd-errorlog-level' to '128',
+    remove aci's to start with a clean slate, and add dummy entries
+    :steps:
+        1. Check we can not delete an entry without the proper SELFDN aci
+        2. Add proper ACI
+        3. Check we can perform delete operation with proper ACI
+    :expectedresults:
+        1. Operation should be successful
+        2. Operation should be successful
+     """
+    topology_st.standalone.log.info("\n\n######################### DELETE ######################\n")
+
+    # bind as bind_entry
+    topology_st.standalone.log.info("Bind as %s" % BIND_DN)
+    topology_st.standalone.simple_bind_s(BIND_DN, BIND_PW)
+
+    # entry to delete WITH member being BIND_DN but WITHOUT the ACI -> ldap.INSUFFICIENT_ACCESS
+    try:
+        topology_st.standalone.log.info("Try to delete  %s (aci is missing)" % ENTRY_DN)
+        topology_st.standalone.delete_s(ENTRY_DN)
+    except Exception as e:
+        topology_st.standalone.log.info("Exception (expected): %s" % type(e).__name__)
+        assert isinstance(e, ldap.INSUFFICIENT_ACCESS)
+
+    # Ok Now add the proper ACI
+    topology_st.standalone.log.info("Bind as %s and add the READ/SEARCH SELFDN aci" % DN_DM)
+    topology_st.standalone.simple_bind_s(DN_DM, PASSWORD)
+
+    ACI_TARGET = "(target = \"ldap:///cn=*,%s\")" % SUFFIX
+    ACI_TARGETFILTER = "(targetfilter =\"(objectClass=%s)\")" % OC_NAME
+    ACI_ALLOW = "(version 3.0; acl \"SelfDN delete\"; allow (delete)"
+    ACI_SUBJECT = " userattr = \"member#selfDN\";)"
+    ACI_BODY = ACI_TARGET + ACI_TARGETFILTER + ACI_ALLOW + ACI_SUBJECT
+    mod = [(ldap.MOD_ADD, 'aci', ensure_bytes(ACI_BODY))]
+    topology_st.standalone.modify_s(SUFFIX, mod)
+
+    # bind as bind_entry
+    topology_st.standalone.log.info("Bind as %s" % BIND_DN)
+    topology_st.standalone.simple_bind_s(BIND_DN, BIND_PW)
+
+    # entry to delete with the proper aci
+    topology_st.standalone.log.info("Try to delete  %s should be successful" % ENTRY_DN)
+    topology_st.standalone.delete_s(ENTRY_DN)
+
+
+if __name__ == '__main__':
+    # Run isolated
+    # -s for DEBUG mode
+    CURRENT_FILE = os.path.realpath(__file__)
+    pytest.main("-s %s" % CURRENT_FILE)
diff --git a/dirsrvtests/tests/suites/plugins/attr_nsslapd-pluginarg_test.py b/dirsrvtests/tests/suites/plugins/attr_nsslapd-pluginarg_test.py
new file mode 100644
index 0000000..4dee6a0
--- /dev/null
+++ b/dirsrvtests/tests/suites/plugins/attr_nsslapd-pluginarg_test.py
@@ -0,0 +1,210 @@
+# --- BEGIN COPYRIGHT BLOCK ---
+# Copyright (C) 2016 Red Hat, Inc.
+# All rights reserved.
+#
+# License: GPL (version 3 or any later version).
+# See LICENSE for details.
+# --- END COPYRIGHT BLOCK ---
+#
+import pytest
+from lib389.tasks import *
+from lib389.utils import *
+from lib389.topologies import topology_st
+
+from lib389._constants import DEFAULT_SUFFIX, DN_PLUGIN, SUFFIX, PLUGIN_7_BIT_CHECK
+
+# Skip on older versions
+pytestmark = pytest.mark.skipif(ds_is_older('1.3'), reason="Not implemented")
+
+logging.getLogger(__name__).setLevel(logging.DEBUG)
+log = logging.getLogger(__name__)
+
+DN_7BITPLUGIN = "cn=7-bit check,%s" % DN_PLUGIN
+ATTRS = ["uid", "mail", "userpassword", ",", SUFFIX, None]
+
+
+@pytest.fixture(scope="module")
+def enable_plugin(topology_st):
+    """Enabling the 7-bit plugin for the
+    environment setup"""
+    log.info("Ticket 47431 - 0: Enable 7bit plugin...")
+    topology_st.standalone.plugins.enable(name=PLUGIN_7_BIT_CHECK)
+
+
+@pytest.mark.ds47431
+def test_duplicate_values(topology_st, enable_plugin):
+    """Check 26 duplicate values are treated as one
+
+    :id: b23e04f1-2757-42cc-b3a2-26426c903f6d
+    :setup: Standalone instance, enable 7bit plugin
+    :steps:
+        1. Modify the entry for cn=7-bit check,cn=plugins,cn=config as :
+           nsslapd-pluginarg0 : uid
+           nsslapd-pluginarg1 : mail
+           nsslapd-pluginarg2 : userpassword
+           nsslapd-pluginarg3 : ,
+           nsslapd-pluginarg4 : dc=example,dc=com
+        2. Set nsslapd-pluginarg2 to 'userpassword' for multiple time (ideally 27)
+        3. Check whether duplicate values are treated as one
+    :expectedresults:
+        1. It should be modified successfully
+        2. It should be successful
+        3. It should be successful
+     """
+
+    log.info("Ticket 47431 - 1: Check 26 duplicate values are treated as one...")
+    expected = "str2entry_dupcheck.* duplicate values for attribute type nsslapd-pluginarg2 detected in entry cn=7-bit check,cn=plugins,cn=config."
+
+    log.debug('modify_s %s' % DN_7BITPLUGIN)
+    topology_st.standalone.modify_s(DN_7BITPLUGIN,
+                                    [(ldap.MOD_REPLACE, 'nsslapd-pluginarg0', b"uid"),
+                                     (ldap.MOD_REPLACE, 'nsslapd-pluginarg1', b"mail"),
+                                     (ldap.MOD_REPLACE, 'nsslapd-pluginarg2', b"userpassword"),
+                                     (ldap.MOD_REPLACE, 'nsslapd-pluginarg3', b","),
+                                     (ldap.MOD_REPLACE, 'nsslapd-pluginarg4', ensure_bytes(SUFFIX))])
+
+    arg2 = "nsslapd-pluginarg2: userpassword"
+    topology_st.standalone.stop()
+    dse_ldif = topology_st.standalone.confdir + '/dse.ldif'
+    os.system('mv %s %s.47431' % (dse_ldif, dse_ldif))
+    os.system(
+        'sed -e "s/\\(%s\\)/\\1\\n\\1\\n\\1\\n\\1\\n\\1\\n\\1\\n\\1\\n\\1\\n\\1\\n\\1\\n\\1\\n\\1\\n\\1\\n\\1\\n\\1\\n\\1\\n\\1\\n\\1\\n\\1\\n\\1\\n\\1\\n\\1\\n\\1\\n\\1\\n\\1\\n\\1\\n\\1/" %s.47431 > %s' % (
+        arg2, dse_ldif, dse_ldif))
+    topology_st.standalone.start()
+
+    cmdline = 'egrep -i "%s" %s' % (expected, topology_st.standalone.errlog)
+    p = os.popen(cmdline, "r")
+    line = p.readline()
+    if line == "":
+        log.error('Expected error "%s" not logged in %s' % (expected, topology_st.standalone.errlog))
+        assert False
+    else:
+        log.debug('line: %s' % line)
+        log.info('Expected error "%s" logged in %s' % (expected, topology_st.standalone.errlog))
+
+    log.info("Ticket 47431 - 1: done")
+
+
+@pytest.mark.ds47431
+def test_multiple_value(topology_st, enable_plugin):
+    """Check two values belonging to one arg is fixed
+
+    :id: 20c802bc-332f-4e8d-bcfb-8cd28123d695
+    :setup: Standalone instance, enable 7bit plugin
+    :steps:
+        1. Modify the entry for cn=7-bit check,cn=plugins,cn=config as :
+           nsslapd-pluginarg0 : uid
+           nsslapd-pluginarg0 : mail
+           nsslapd-pluginarg1 : userpassword
+           nsslapd-pluginarg2 : ,
+           nsslapd-pluginarg3 : dc=example,dc=com
+           nsslapd-pluginarg4 : None
+           (Note : While modifying add two attributes entries for nsslapd-pluginarg0)
+
+        2. Check two values belonging to one arg is fixed
+    :expectedresults:
+        1. Entries should be modified successfully
+        2. Operation should be successful
+     """
+
+    log.info("Ticket 47431 - 2: Check two values belonging to one arg is fixed...")
+
+    topology_st.standalone.modify_s(DN_7BITPLUGIN,
+                                    [(ldap.MOD_REPLACE, 'nsslapd-pluginarg0', b"uid"),
+                                     (ldap.MOD_ADD, 'nsslapd-pluginarg0', b"mail"),
+                                     (ldap.MOD_REPLACE, 'nsslapd-pluginarg1', b"userpassword"),
+                                     (ldap.MOD_REPLACE, 'nsslapd-pluginarg2', b","),
+                                     (ldap.MOD_REPLACE, 'nsslapd-pluginarg3', ensure_bytes(SUFFIX)),
+                                     (ldap.MOD_DELETE, 'nsslapd-pluginarg4', None)])
+
+    # PLUGIN LOG LEVEL
+    topology_st.standalone.modify_s(DN_CONFIG, [(ldap.MOD_REPLACE, 'nsslapd-errorlog-level', b'65536')])
+
+    topology_st.standalone.restart()
+
+    cmdline = 'egrep -i %s %s' % ("NS7bitAttr_Init", topology_st.standalone.errlog)
+    p = os.popen(cmdline, "r")
+    i = 0
+    while ATTRS[i]:
+        line = p.readline()
+        log.debug('line - %s' % line)
+        log.debug('ATTRS[%d] %s' % (i, ATTRS[i]))
+        if line == "":
+            break
+        elif line.find(ATTRS[i]) >= 0:
+            log.debug('%s was logged' % ATTRS[i])
+        else:
+            log.error('%s was not logged.' % ATTRS[i])
+            assert False
+        i = i + 1
+
+    log.info("Ticket 47431 - 2: done")
+
+
+@pytest.mark.ds47431
+def test_missing_args(topology_st, enable_plugin):
+    """Check missing args are fixed
+
+    :id: b2814399-7ed2-4fe0-981d-b0bdbbe31cfb
+    :setup: Standalone instance, enable 7bit plugin
+    :steps:
+        1. Modify the entry for cn=7-bit check,cn=plugins,cn=config as :
+           nsslapd-pluginarg0 : None
+           nsslapd-pluginarg1 : uid
+           nsslapd-pluginarg2 : None
+           nsslapd-pluginarg3 : mail
+           nsslapd-pluginarg5 : userpassword
+           nsslapd-pluginarg7 : ,
+           nsslapd-pluginarg9 : dc=example,dc=com
+           (Note: While modifying add 2 entries as None)
+
+        2. Change the nsslapd-errorlog-level to 65536
+        3. Check missing agrs are fixed
+    :expectedresults:
+        1. Entries should be modified successfully
+        2. Operation should be successful
+        3. Operation should be successful
+     """
+
+    log.info("Ticket 47431 - 3: Check missing args are fixed...")
+
+    topology_st.standalone.modify_s(DN_7BITPLUGIN,
+                                    [(ldap.MOD_DELETE, 'nsslapd-pluginarg0', None),
+                                     (ldap.MOD_REPLACE, 'nsslapd-pluginarg1', b"uid"),
+                                     (ldap.MOD_DELETE, 'nsslapd-pluginarg2', None),
+                                     (ldap.MOD_REPLACE, 'nsslapd-pluginarg3', b"mail"),
+                                     (ldap.MOD_REPLACE, 'nsslapd-pluginarg5', b"userpassword"),
+                                     (ldap.MOD_REPLACE, 'nsslapd-pluginarg7', b","),
+                                     (ldap.MOD_REPLACE, 'nsslapd-pluginarg9', ensure_bytes(SUFFIX))])
+
+    # PLUGIN LOG LEVEL
+    topology_st.standalone.modify_s(DN_CONFIG, [(ldap.MOD_REPLACE, 'nsslapd-errorlog-level', b'65536')])
+
+    topology_st.standalone.stop()
+    os.system('mv %s %s.47431' % (topology_st.standalone.errlog, topology_st.standalone.errlog))
+    os.system('touch %s' % (topology_st.standalone.errlog))
+    topology_st.standalone.start()
+
+    cmdline = 'egrep -i %s %s' % ("NS7bitAttr_Init", topology_st.standalone.errlog)
+    p = os.popen(cmdline, "r")
+    i = 0
+    while ATTRS[i]:
+        line = p.readline()
+        if line == "":
+            break
+        elif line.find(ATTRS[i]) >= 0:
+            log.debug('%s was logged' % ATTRS[i])
+        else:
+            log.error('%s was not logged.' % ATTRS[i])
+            assert False
+        i = i + 1
+
+    log.info("Ticket 47431 - 3: done")
+    log.info('Test complete')
+
+
+if __name__ == '__main__':
+    # Run isolated
+    # -s for DEBUG mode
+    CURRENT_FILE = os.path.realpath(__file__)
+    pytest.main("-s %s" % CURRENT_FILE)
diff --git a/dirsrvtests/tests/suites/replication/changelog_test.py b/dirsrvtests/tests/suites/replication/changelog_test.py
index 3b5d547..b4ae7c6 100755
--- a/dirsrvtests/tests/suites/replication/changelog_test.py
+++ b/dirsrvtests/tests/suites/replication/changelog_test.py
@@ -16,9 +16,17 @@ from lib389.replica import Replicas
 from lib389.idm.user import UserAccounts
 from lib389.topologies import topology_m2 as topo
 from lib389._constants import *
+from lib389.tasks import *
+from lib389.utils import *
 
 TEST_ENTRY_NAME = 'replusr'
 NEW_RDN_NAME = 'cl5usr'
+CHANGELOG = 'cn=changelog5,cn=config'
+RETROCHANGELOG = 'cn=Retro Changelog Plugin,cn=plugins,cn=config'
+MAXAGE = 'nsslapd-changelogmaxage'
+TRIMINTERVAL = 'nsslapd-changelogtrim-interval'
+COMPACTDBINTERVAL = 'nsslapd-changelogcompactdb-interval'
+FILTER = '(cn=*)'
 
 DEBUGGING = os.getenv('DEBUGGING', default=False)
 if DEBUGGING:
@@ -109,6 +117,84 @@ def _check_changelog_ldif(topo, changelog_ldif):
             changetype operations'
 
 
+def get_ldap_error_msg(e, type):
+    return e.args[0][type]
+
+
+@pytest.fixture(scope="module")
+def changelog_init(topo):
+    """Initialize the test environment by changing log dir and
+    enabling cn=Retro Changelog Plugin,cn=plugins,cn=config
+     """
+    log.info('Testing Ticket 47669 - Test duration syntax in the changelogs')
+
+    # bind as directory manager
+    topo.ms["master1"].log.info("Bind as %s" % DN_DM)
+    topo.ms["master1"].simple_bind_s(DN_DM, PASSWORD)
+
+    try:
+        changelogdir = os.path.join(os.path.dirname(topo.ms["master1"].dbdir), 'changelog')
+        topo.ms["master1"].modify_s(CHANGELOG, [(ldap.MOD_REPLACE, 'nsslapd-changelogdir',
+                                                                    ensure_bytes(changelogdir))])
+    except ldap.LDAPError as e:
+        log.error('Failed to modify ' + CHANGELOG + ': error {}'.format(get_ldap_error_msg(e,'desc')))
+        assert False
+
+    try:
+        topo.ms["master1"].modify_s(RETROCHANGELOG, [(ldap.MOD_REPLACE, 'nsslapd-pluginEnabled', b'on')])
+    except ldap.LDAPError as e:
+        log.error('Failed to enable ' + RETROCHANGELOG + ': error {}'.format(get_ldap_error_msg(e, 'desc')))
+        assert False
+
+    # restart the server
+    topo.ms["master1"].restart(timeout=10)
+
+
+def add_and_check(topo, plugin, attr, val, isvalid):
+    """
+    Helper function to add/replace attr: val and check the added value
+    """
+    if isvalid:
+        log.info('Test %s: %s -- valid' % (attr, val))
+        try:
+            topo.ms["master1"].modify_s(plugin, [(ldap.MOD_REPLACE, attr, ensure_bytes(val))])
+        except ldap.LDAPError as e:
+            log.error('Failed to add ' + attr + ': ' + val + ' to ' + plugin + ': error {}'.format(get_ldap_error_msg(e,'desc')))
+            assert False
+    else:
+        log.info('Test %s: %s -- invalid' % (attr, val))
+        if plugin == CHANGELOG:
+            try:
+                topo.ms["master1"].modify_s(plugin, [(ldap.MOD_REPLACE, attr, ensure_bytes(val))])
+            except ldap.LDAPError as e:
+                log.error('Expectedly failed to add ' + attr + ': ' + val +
+                          ' to ' + plugin + ': error {}'.format(get_ldap_error_msg(e,'desc')))
+        else:
+            try:
+                topo.ms["master1"].modify_s(plugin, [(ldap.MOD_REPLACE, attr, ensure_bytes(val))])
+            except ldap.LDAPError as e:
+                log.error('Failed to add ' + attr + ': ' + val + ' to ' + plugin + ': error {}'.format(get_ldap_error_msg(e,'desc')))
+
+    try:
+        entries = topo.ms["master1"].search_s(plugin, ldap.SCOPE_BASE, FILTER, [attr])
+        if isvalid:
+            if not entries[0].hasValue(attr, val):
+                log.fatal('%s does not have expected (%s: %s)' % (plugin, attr, val))
+                assert False
+        else:
+            if plugin == CHANGELOG:
+                if entries[0].hasValue(attr, val):
+                    log.fatal('%s has unexpected (%s: %s)' % (plugin, attr, val))
+                    assert False
+            else:
+                if not entries[0].hasValue(attr, val):
+                    log.fatal('%s does not have expected (%s: %s)' % (plugin, attr, val))
+                    assert False
+    except ldap.LDAPError as e:
+        log.fatal('Unable to search for entry %s: error %s' % (plugin, e.message['desc']))
+        assert False
+
+
 def test_verify_changelog(topo):
     """Check if changelog dump file contains required ldap operations
 
@@ -230,8 +316,143 @@ def test_verify_changelog_offline_backup(topo):
     _check_changelog_ldif(topo, changelog_ldif)
 
 
+@pytest.mark.ds47669
+def test_changelog_maxage(topo, changelog_init):
+    """Check nsslapd-changelog max age values
+
+    :id: d284ff27-03b2-412c-ac74-ac4f2d2fae3b
+    :setup: Replication with two master, change nsslapd-changelogdir to
+    '/var/lib/dirsrv/slapd-master1/changelog' and
+    set cn=Retro Changelog Plugin,cn=plugins,cn=config to 'on'
+    :steps:
+        1. Set nsslapd-changelogmaxage in cn=changelog5,cn=config to values - '12345','10s','30M','12h','2D','4w'
+        2. Set nsslapd-changelogmaxage in cn=changelog5,cn=config to values - '-123','xyz'
+
+    :expectedresults:
+        1. Operation should be successful
+        2. Operation should be unsuccessful
+     """
+    log.info('1. Test nsslapd-changelogmaxage in cn=changelog5,cn=config')
+
+    # bind as directory manager
+    topo.ms["master1"].log.info("Bind as %s" % DN_DM)
+    topo.ms["master1"].simple_bind_s(DN_DM, PASSWORD)
+
+    add_and_check(topo, CHANGELOG, MAXAGE, '12345', True)
+    add_and_check(topo, CHANGELOG, MAXAGE, '10s', True)
+    add_and_check(topo, CHANGELOG, MAXAGE, '30M', True)
+    add_and_check(topo, CHANGELOG, MAXAGE, '12h', True)
+    add_and_check(topo, CHANGELOG, MAXAGE, '2D', True)
+    add_and_check(topo, CHANGELOG, MAXAGE, '4w', True)
+    add_and_check(topo, CHANGELOG, MAXAGE, '-123', False)
+    add_and_check(topo, CHANGELOG, MAXAGE, 'xyz', False)
+
+
+@pytest.mark.ds47669
+def test_ticket47669_changelog_triminterval(topo, changelog_init):
+    """Check nsslapd-changelog triminterval values
+
+    :id: 8f850c37-7e7c-49dd-a4e0-9344638616d6
+    :setup: Replication with two master, change nsslapd-changelogdir to
+    '/var/lib/dirsrv/slapd-master1/changelog' and
+    set cn=Retro Changelog Plugin,cn=plugins,cn=config to 'on'
+    :steps:
+        1. Set nsslapd-changelogtrim-interval in cn=changelog5,cn=config to values -
+           '12345','10s','30M','12h','2D','4w'
+        2. Set nsslapd-changelogtrim-interval in cn=changelog5,cn=config to values - '-123','xyz'
+
+    :expectedresults:
+        1. Operation should be successful
+        2. Operation should be unsuccessful
+     """
+    log.info('2. Test nsslapd-changelogtrim-interval in cn=changelog5,cn=config')
+
+    # bind as directory manager
+    topo.ms["master1"].log.info("Bind as %s" % DN_DM)
+    topo.ms["master1"].simple_bind_s(DN_DM, PASSWORD)
+
+    add_and_check(topo, CHANGELOG, TRIMINTERVAL, '12345', True)
+    add_and_check(topo, CHANGELOG, TRIMINTERVAL, '10s', True)
+    add_and_check(topo, CHANGELOG, TRIMINTERVAL, '30M', True)
+    add_and_check(topo, CHANGELOG, TRIMINTERVAL, '12h', True)
+    add_and_check(topo, CHANGELOG, TRIMINTERVAL, '2D', True)
+    add_and_check(topo, CHANGELOG, TRIMINTERVAL, '4w', True)
+    add_and_check(topo, CHANGELOG, TRIMINTERVAL, '-123', False)
+    add_and_check(topo, CHANGELOG, TRIMINTERVAL, 'xyz', False)
+
+
+@pytest.mark.ds47669
+def test_changelog_compactdbinterval(topo, changelog_init):
+    """Check nsslapd-changelog compactdbinterval values
+
+    :id: 0f4b3118-9dfa-4c2a-945c-72847b42a48c
+    :setup: Replication with two master, change nsslapd-changelogdir to
+    '/var/lib/dirsrv/slapd-master1/changelog' and
+    set cn=Retro Changelog Plugin,cn=plugins,cn=config to 'on'
+    :steps:
+        1. Set nsslapd-changelogcompactdb-interval in cn=changelog5,cn=config to values -
+           '12345','10s','30M','12h','2D','4w'
+        2. Set nsslapd-changelogcompactdb-interval in cn=changelog5,cn=config to values -
+           '-123','xyz'
+
+    :expectedresults:
+        1. Operation should be successful
+        2. Operation should be unsuccessful
+     """
+    log.info('3. Test nsslapd-changelogcompactdb-interval in cn=changelog5,cn=config')
+
+    # bind as directory manager
+    topo.ms["master1"].log.info("Bind as %s" % DN_DM)
+    topo.ms["master1"].simple_bind_s(DN_DM, PASSWORD)
+
+    add_and_check(topo, CHANGELOG, COMPACTDBINTERVAL, '12345', True)
+    add_and_check(topo, CHANGELOG, COMPACTDBINTERVAL, '10s', True)
+    add_and_check(topo, CHANGELOG, COMPACTDBINTERVAL, '30M', True)
+    add_and_check(topo, CHANGELOG, COMPACTDBINTERVAL, '12h', True)
+    add_and_check(topo, CHANGELOG, COMPACTDBINTERVAL, '2D', True)
+    add_and_check(topo, CHANGELOG, COMPACTDBINTERVAL, '4w', True)
+    add_and_check(topo, CHANGELOG, COMPACTDBINTERVAL, '-123', False)
+    add_and_check(topo, CHANGELOG, COMPACTDBINTERVAL, 'xyz', False)
+
+
+@pytest.mark.ds47669
+def test_retrochangelog_maxage(topo, changelog_init):
+    """Check nsslapd-retrochangelog max age values
+
+    :id: 0cb84d81-3e86-4dbf-84a2-66aefd8281db
+    :setup: Replication with two master, change nsslapd-changelogdir to
+    '/var/lib/dirsrv/slapd-master1/changelog' and
+    set cn=Retro Changelog Plugin,cn=plugins,cn=config to 'on'
+    :steps:
+        1. Set nsslapd-changelogmaxage in cn=Retro Changelog Plugin,cn=plugins,cn=config to values -
+           '12345','10s','30M','12h','2D','4w'
+        2. Set nsslapd-changelogmaxage in cn=Retro Changelog Plugin,cn=plugins,cn=config to values -
+           '-123','xyz'
+
+    :expectedresults:
+        1. Operation should be successful
+        2. Operation should be unsuccessful
+     """
+    log.info('4. Test nsslapd-changelogmaxage in cn=Retro Changelog Plugin,cn=plugins,cn=config')
+
+    # bind as directory manager
+    topo.ms["master1"].log.info("Bind as %s" % DN_DM)
+    topo.ms["master1"].simple_bind_s(DN_DM, PASSWORD)
+
+    add_and_check(topo, RETROCHANGELOG, MAXAGE, '12345', True)
+    add_and_check(topo, RETROCHANGELOG, MAXAGE, '10s', True)
+    add_and_check(topo, RETROCHANGELOG, MAXAGE, '30M', True)
+    add_and_check(topo, RETROCHANGELOG, MAXAGE, '12h', True)
+    add_and_check(topo, RETROCHANGELOG, MAXAGE, '2D', True)
+    add_and_check(topo, RETROCHANGELOG, MAXAGE, '4w', True)
+    add_and_check(topo, RETROCHANGELOG, MAXAGE, '-123', False)
+    add_and_check(topo, RETROCHANGELOG, MAXAGE, 'xyz', False)
+
+    topo.ms["master1"].log.info("ticket47669 was successfully verified.")
+
+
 if __name__ == '__main__':
     # Run isolated
     # -s for DEBUG mode
     CURRENT_FILE = os.path.realpath(__file__)
-    pytest.main('-s {}'.format(CURRENT_FILE))
+    pytest.main("-s %s" % CURRENT_FILE)
diff --git a/dirsrvtests/tests/suites/schema/schema_replication_test.py b/dirsrvtests/tests/suites/schema/schema_replication_test.py
new file mode 100644
index 0000000..00568c8
--- /dev/null
+++ b/dirsrvtests/tests/suites/schema/schema_replication_test.py
@@ -0,0 +1,701 @@
+# --- BEGIN COPYRIGHT BLOCK ---
+# Copyright (C) 2016 Red Hat, Inc.
+# All rights reserved.
+#
+# License: GPL (version 3 or any later version).
+# See LICENSE for details.
+# --- END COPYRIGHT BLOCK ---
+#
+'''
+Created on Nov 7, 2013
+
+@author: tbordaz
+'''
+import logging
+import re
+import time
+
+import ldap
+import pytest
+from lib389 import Entry
+from lib389._constants import *
+from lib389.topologies import topology_m1c1
+
+from lib389.utils import *
+
+# Skip on older versions
+pytestmark = pytest.mark.skipif(ds_is_older('1.3'), reason="Not implemented")
+logging.getLogger(__name__).setLevel(logging.DEBUG)
+log = logging.getLogger(__name__)
+
+TEST_REPL_DN = "cn=test_repl, %s" % SUFFIX
+ENTRY_DN = "cn=test_entry, %s" % SUFFIX
+MUST_OLD = "(postalAddress $ preferredLocale)"
+MUST_NEW = "(postalAddress $ preferredLocale $ telexNumber)"
+MAY_OLD = "(postalCode $ street)"
+MAY_NEW = "(postalCode $ street $ postOfficeBox)"
+
+
+def _header(topology_m1c1, label):
+    topology_m1c1.ms["master1"].log.info("\n\n###############################################")
+    topology_m1c1.ms["master1"].log.info("#######")
+    topology_m1c1.ms["master1"].log.info("####### %s" % label)
+    topology_m1c1.ms["master1"].log.info("#######")
+    topology_m1c1.ms["master1"].log.info("###################################################")
+
+
+def pattern_errorlog(file, log_pattern):
+    try:
+        pattern_errorlog.last_pos += 1
+    except AttributeError:
+        pattern_errorlog.last_pos = 0
+
+    found = None
+    log.debug("_pattern_errorlog: start at offset %d" % pattern_errorlog.last_pos)
+    file.seek(pattern_errorlog.last_pos)
+
+    # Use a while true iteration because 'for line in file: hit a
+    # python bug that break file.tell()
+    while True:
+        line = file.readline()
+        log.debug("_pattern_errorlog: [%d] %s" % (file.tell(), line))
+        found = log_pattern.search(line)
+        if ((line == '') or (found)):
+            break
+
+    log.debug("_pattern_errorlog: end at offset %d" % file.tell())
+    pattern_errorlog.last_pos = file.tell()
+    return found
+
+
+def _oc_definition(oid_ext, name, must=None, may=None):
+    oid = "1.2.3.4.5.6.7.8.9.10.%d" % oid_ext
+    desc = 'To test ticket 47490'
+    sup = 'person'
+    if not must:
+        must = MUST_OLD
+    if not may:
+        may = MAY_OLD
+
+    new_oc = "( %s  NAME '%s' DESC '%s' SUP %s AUXILIARY MUST %s MAY %s )" % (oid, name, desc, sup, must, may)
+    return new_oc
+
+
+def add_OC(instance, oid_ext, name):
+    new_oc = _oc_definition(oid_ext, name)
+    instance.schema.add_schema('objectClasses', ensure_bytes(new_oc))
+
+
+def mod_OC(instance, oid_ext, name, old_must=None, old_may=None, new_must=None, new_may=None):
+    old_oc = _oc_definition(oid_ext, name, old_must, old_may)
+    new_oc = _oc_definition(oid_ext, name, new_must, new_may)
+    instance.schema.del_schema('objectClasses', ensure_bytes(old_oc))
+    instance.schema.add_schema('objectClasses', ensure_bytes(new_oc))
+
+
+def support_schema_learning(topology_m1c1):
+    """
+    with https://fedorahosted.org/389/ticket/47721, the supplier and consumer can learn
+    schema definitions when a replication occurs.
+    Before that ticket: replication of the schema fails requiring administrative operation
+    In the test the schemaCSN (master consumer) differs
+
+    After that ticket: replication of the schema succeeds (after an initial phase of learning)
+    In the test the schema CSN (master consumer) are in sync
+
+    This function returns True if 47721 is fixed in the current release
+    False else
+    """
+    ent = topology_m1c1.cs["consumer1"].getEntry(DN_CONFIG, ldap.SCOPE_BASE, "(cn=config)", ['nsslapd-versionstring'])
+    if ent.hasAttr('nsslapd-versionstring'):
+        val = ent.getValue('nsslapd-versionstring')
+        version = ensure_str(val).split('/')[1].split('.')  # something like ['1', '3', '1', '23', 'final_fix']
+        major = int(version[0])
+        minor = int(version[1])
+        if major > 1:
+            return True
+        if minor > 3:
+            # version is 1.4 or after
+            return True
+        if minor == 3:
+            if version[2].isdigit():
+                if int(version[2]) >= 3:
+                    return True
+        return False
+
+
+def trigger_update(topology_m1c1):
+    """
+        It triggers an update on the supplier. This will start a replication
+        session and a schema push
+    """
+    try:
+        trigger_update.value += 1
+    except AttributeError:
+        trigger_update.value = 1
+    replace = [(ldap.MOD_REPLACE, 'telephonenumber', ensure_bytes(str(trigger_update.value)))]
+    topology_m1c1.ms["master1"].modify_s(ENTRY_DN, replace)
+
+    # wait 10 seconds that the update is replicated
+    loop = 0
+    while loop <= 10:
+        try:
+            ent = topology_m1c1.cs["consumer1"].getEntry(ENTRY_DN, ldap.SCOPE_BASE, "(objectclass=*)",
+                                                         ['telephonenumber'])
+            val = ent.telephonenumber or "0"
+            if int(val) == trigger_update.value:
+                return
+            # the expected value is not yet replicated. try again
+            time.sleep(1)
+            loop += 1
+            log.debug("trigger_update: receive %s (expected %d)" % (val, trigger_update.value))
+        except ldap.NO_SUCH_OBJECT:
+            time.sleep(1)
+            loop += 1
+
+
+def trigger_schema_push(topology_m1c1):
+    '''
+    Trigger update to create a replication session.
+    In case of 47721 is fixed and the replica needs to learn the missing definition, then
+    the first replication session learn the definition and the second replication session
+    push the schema (and the schemaCSN.
+    This is why there is two updates and replica agreement is stopped/start (to create a second session)
+    '''
+    agreements = topology_m1c1.ms["master1"].agreement.list(suffix=SUFFIX,
+                                                            consumer_host=topology_m1c1.cs["consumer1"].host,
+                                                            consumer_port=topology_m1c1.cs["consumer1"].port)
+    assert (len(agreements) == 1)
+    ra = agreements[0]
+    trigger_update(topology_m1c1)
+    topology_m1c1.ms["master1"].agreement.pause(ra.dn)
+    topology_m1c1.ms["master1"].agreement.resume(ra.dn)
+    trigger_update(topology_m1c1)
+
+
+@pytest.fixture(scope="module")
+def schema_replication_init(topology_m1c1):
+    """Initialize the test environment
+
+    """
+    log.debug("test_schema_replication_init topology_m1c1 %r (master %r, consumer %r" % (
+    topology_m1c1, topology_m1c1.ms["master1"], topology_m1c1.cs["consumer1"]))
+    # check if a warning message is logged in the
+    # error log of the supplier
+    topology_m1c1.ms["master1"].errorlog_file = open(topology_m1c1.ms["master1"].errlog, "r")
+
+    # This entry will be used to trigger attempt of schema push
+    topology_m1c1.ms["master1"].add_s(Entry((ENTRY_DN, {
+        'objectclass': "top person".split(),
+        'sn': 'test_entry',
+        'cn': 'test_entry'})))
+
+
+@pytest.mark.ds47490
+def test_schema_replication_one(topology_m1c1, schema_replication_init):
+    """Check supplier schema is a superset (one extra OC) of consumer schema, then
+    schema is pushed and there is no message in the error log
+
+    :id: d6c6ff30-b3ae-4001-80ff-0fb18563a393
+    :setup: Master Consumer, check if a warning message is logged in the
+    error log of the supplier and add a test entry to trigger attempt of schema push.
+    :steps:
+        1. Update the schema of supplier, so it will be superset of consumer
+        2. Push the Schema (no error)
+        3. Check both master and consumer has same schemaCSN
+        4. Check the startup/final state
+    :expectedresults:
+        1. Operation should be successful
+        2. Operation should be successful
+        3. Operation should be successful
+        4. State at startup:
+            - supplier default schema
+            - consumer default schema
+           Final state
+            - supplier +masterNewOCA
+            - consumer +masterNewOCA
+    """
+
+    _header(topology_m1c1, "Extra OC Schema is pushed - no error")
+
+    log.debug("test_schema_replication_one topology_m1c1 %r (master %r, consumer %r" % (
+    topology_m1c1, topology_m1c1.ms["master1"], topology_m1c1.cs["consumer1"]))
+    # update the schema of the supplier so that it is a superset of
+    # consumer. Schema should be pushed
+    add_OC(topology_m1c1.ms["master1"], 2, 'masterNewOCA')
+
+    trigger_schema_push(topology_m1c1)
+    master_schema_csn = topology_m1c1.ms["master1"].schema.get_schema_csn()
+    consumer_schema_csn = topology_m1c1.cs["consumer1"].schema.get_schema_csn()
+
+    # Check the schemaCSN was updated on the consumer
+    log.debug("test_schema_replication_one master_schema_csn=%s", master_schema_csn)
+    log.debug("ctest_schema_replication_one onsumer_schema_csn=%s", consumer_schema_csn)
+    assert master_schema_csn == consumer_schema_csn
+
+    # Check the error log of the supplier does not contain an error
+    regex = re.compile("must not be overwritten \(set replication log for additional info\)")
+    res = pattern_errorlog(topology_m1c1.ms["master1"].errorlog_file, regex)
+    if res is not None:
+        assert False
+
+
+@pytest.mark.ds47490
+def test_schema_replication_two(topology_m1c1, schema_replication_init):
+    """Check consumer schema is a superset (one extra OC) of supplier schema, then
+        schema is pushed and there is a message in the error log
+
+    :id: b5db9b75-a9a7-458e-86ec-2a8e7bd1c014
+    :setup: Master Consumer, check if a warning message is logged in the
+    error log of the supplier and add a test entry to trigger attempt of schema push.
+    :steps:
+        1. Update the schema of consumer, so it will be superset of supplier
+        2. Update the schema of supplier so ti make it's nsSchemaCSN larger than consumer
+        3. Push the Schema (error should be generated)
+        4. Check supplier learns the missing definition
+        5. Check the error logs
+        6. Check the startup/final state
+    :expectedresults:
+        1. Operation should be successful
+        2. Operation should be successful
+        3. Operation should be successful
+        4. Operation should be successful
+        5. Operation should be successful
+        6. State at startup
+            - supplier +masterNewOCA
+            - consumer +masterNewOCA
+           Final state
+            - supplier +masterNewOCA +masterNewOCB
+            - consumer +masterNewOCA               +consumerNewOCA
+    """
+
+    _header(topology_m1c1, "Extra OC Schema is pushed - (ticket 47721 allows to learn missing def)")
+
+    # add this OC on consumer. Supplier will no push the schema
+    add_OC(topology_m1c1.cs["consumer1"], 1, 'consumerNewOCA')
+
+    # add a new OC on the supplier so that its nsSchemaCSN is larger than the consumer (wait 2s)
+    time.sleep(2)
+    add_OC(topology_m1c1.ms["master1"], 3, 'masterNewOCB')
+
+    # now push the scheam
+    trigger_schema_push(topology_m1c1)
+    master_schema_csn = topology_m1c1.ms["master1"].schema.get_schema_csn()
+    consumer_schema_csn = topology_m1c1.cs["consumer1"].schema.get_schema_csn()
+
+    # Check the schemaCSN was NOT updated on the consumer
+    # with 47721, supplier learns the missing definition
+    log.debug("test_schema_replication_two master_schema_csn=%s", master_schema_csn)
+    log.debug("test_schema_replication_two consumer_schema_csn=%s", consumer_schema_csn)
+    if support_schema_learning(topology_m1c1):
+        assert master_schema_csn == consumer_schema_csn
+    else:
+        assert master_schema_csn != consumer_schema_csn
+
+    # Check the error log of the supplier does not contain an error
+    # This message may happen during the learning phase
+    regex = re.compile("must not be overwritten \(set replication log for additional info\)")
+    res = pattern_errorlog(topology_m1c1.ms["master1"].errorlog_file, regex)
+
+
+@pytest.mark.ds47490
+def test_schema_replication_three(topology_m1c1, schema_replication_init):
+    """Check supplier schema is again a superset (one extra OC), then
+    schema is pushed and there is no message in the error log
+
+    :id: 45888895-76bc-4cc3-9f90-33a69d027116
+    :setup: Master Consumer, check if a warning message is logged in the
+    error log of the supplier and add a test entry to trigger attempt of schema push.
+    :steps:
+        1. Update the schema of master
+        2. Push the Schema (no error)
+        3. Check the schemaCSN was NOT updated on the consumer
+        4. Check the error logs for no errors
+        5. Check the startup/final state
+    :expectedresults:
+        1. Operation should be successful
+        2. Operation should be successful
+        3. Operation should be successful
+        4. Operation should be successful
+        5. State at startup
+            - supplier +masterNewOCA +masterNewOCB
+            - consumer +masterNewOCA               +consumerNewOCA
+           Final state
+            - supplier +masterNewOCA +masterNewOCB +consumerNewOCA
+            - consumer +masterNewOCA +masterNewOCB +consumerNewOCA
+    """
+    _header(topology_m1c1, "Extra OC Schema is pushed - no error")
+
+    # Do an upate to trigger the schema push attempt
+    # add this OC on consumer. Supplier will no push the schema
+    add_OC(topology_m1c1.ms["master1"], 1, 'consumerNewOCA')
+
+    # now push the scheam
+    trigger_schema_push(topology_m1c1)
+    master_schema_csn = topology_m1c1.ms["master1"].schema.get_schema_csn()
+    consumer_schema_csn = topology_m1c1.cs["consumer1"].schema.get_schema_csn()
+
+    # Check the schemaCSN was NOT updated on the consumer
+    log.debug("test_schema_replication_three master_schema_csn=%s", master_schema_csn)
+    log.debug("test_schema_replication_three consumer_schema_csn=%s", consumer_schema_csn)
+    assert master_schema_csn == consumer_schema_csn
+
+    # Check the error log of the supplier does not contain an error
+    regex = re.compile("must not be overwritten \(set replication log for additional info\)")
+    res = pattern_errorlog(topology_m1c1.ms["master1"].errorlog_file, regex)
+    if res is not None:
+        assert False
+
+
+@pytest.mark.ds47490
+def test_schema_replication_four(topology_m1c1, schema_replication_init):
+    """Check supplier schema is again a superset (OC with more MUST), then
+    schema is pushed and there is no message in the error log
+
+    :id: 39304242-2641-4eb8-a9fb-5ff0cf80718f
+    :setup: Master Consumer, check if a warning message is logged in the
+    error log of the supplier and add a test entry to trigger attempt of schema push.
+    :steps:
+        1. Add telenumber to 'masterNewOCA' on the master
+        2. Push the Schema (no error)
+        3. Check the schemaCSN was updated on the consumer
+        4. Check the error log of the supplier does not contain an error
+        5. Check the startup/final state
+    :expectedresults:
+        1. Operation should be successful
+        2. Operation should be successful
+        3. Operation should be successful
+        4. Operation should be successful
+        5. State at startup
+            - supplier +masterNewOCA +masterNewOCB +consumerNewOCA
+            - consumer +masterNewOCA +masterNewOCB +consumerNewOCA
+           Final state
+            - supplier +masterNewOCA     +masterNewOCB     +consumerNewOCA
+                       +must=telexnumber
+            - consumer +masterNewOCA     +masterNewOCB     +consumerNewOCA
+                       +must=telexnumber
+    """
+    _header(topology_m1c1, "Same OC - extra MUST: Schema is pushed - no error")
+
+    mod_OC(topology_m1c1.ms["master1"], 2, 'masterNewOCA', old_must=MUST_OLD, new_must=MUST_NEW, old_may=MAY_OLD,
+           new_may=MAY_OLD)
+
+    trigger_schema_push(topology_m1c1)
+    master_schema_csn = topology_m1c1.ms["master1"].schema.get_schema_csn()
+    consumer_schema_csn = topology_m1c1.cs["consumer1"].schema.get_schema_csn()
+
+    # Check the schemaCSN was updated on the consumer
+    log.debug("test_schema_replication_four master_schema_csn=%s", master_schema_csn)
+    log.debug("ctest_schema_replication_four onsumer_schema_csn=%s", consumer_schema_csn)
+    assert master_schema_csn == consumer_schema_csn
+
+    # Check the error log of the supplier does not contain an error
+    regex = re.compile("must not be overwritten \(set replication log for additional info\)")
+    res = pattern_errorlog(topology_m1c1.ms["master1"].errorlog_file, regex)
+    if res is not None:
+        assert False
+
+
+@pytest.mark.ds47490
+def test_schema_replication_five(topology_m1c1, schema_replication_init):
+    """Check consumer schema is  a superset (OC with more MUST), then
+    schema is  pushed (fix for 47721) and there is a message in the error log
+
+    :id: 498527df-28c8-4e1a-bc9e-799fd2b7b2bb
+    :setup: Master Consumer, check if a warning message is logged in the
+    error log of the supplier and add a test entry to trigger attempt of schema push.
+    :steps:
+        1. Add telenumber to 'consumerNewOCA' on the consumer
+        2. Add a new OC on the supplier so that its nsSchemaCSN is larger than the consumer
+        3. Push the Schema
+        4. Check the schemaCSN was NOT updated on the consumer
+        5. Check the error log of the supplier contain an error
+        6. Check the startup/final state
+    :expectedresults:
+        1. Operation should be successful
+        2. Operation should be successful
+        3. Operation should be successful
+        4. Operation should be successful
+        5. Operation should be successful
+        6. State at startup
+            - supplier +masterNewOCA     +masterNewOCB     +consumerNewOCA
+                       +must=telexnumber
+            - consumer +masterNewOCA     +masterNewOCB     +consumerNewOCA
+                        +must=telexnumber
+           Final state
+            - supplier +masterNewOCA     +masterNewOCB     +consumerNewOCA    +masterNewOCC
+                       +must=telexnumber
+            - consumer +masterNewOCA     +masterNewOCB     +consumerNewOCA
+                       +must=telexnumber                   +must=telexnumber
+
+           Note: replication log is enabled to get more details
+    """
+    _header(topology_m1c1, "Same OC - extra MUST: Schema is pushed - (fix for 47721)")
+
+    # get more detail why it fails
+    topology_m1c1.ms["master1"].enableReplLogging()
+
+    # add telenumber to 'consumerNewOCA' on the consumer
+    mod_OC(topology_m1c1.cs["consumer1"], 1, 'consumerNewOCA', old_must=MUST_OLD, new_must=MUST_NEW, old_may=MAY_OLD,
+           new_may=MAY_OLD)
+    # add a new OC on the supplier so that its nsSchemaCSN is larger than the consumer (wait 2s)
+    time.sleep(2)
+    add_OC(topology_m1c1.ms["master1"], 4, 'masterNewOCC')
+
+    trigger_schema_push(topology_m1c1)
+    master_schema_csn = topology_m1c1.ms["master1"].schema.get_schema_csn()
+    consumer_schema_csn = topology_m1c1.cs["consumer1"].schema.get_schema_csn()
+
+    # Check the schemaCSN was NOT updated on the consumer
+    # with 47721, supplier learns the missing definition
+    log.debug("test_schema_replication_five master_schema_csn=%s", master_schema_csn)
+    log.debug("ctest_schema_replication_five onsumer_schema_csn=%s", consumer_schema_csn)
+    if support_schema_learning(topology_m1c1):
+        assert master_schema_csn == consumer_schema_csn
+    else:
+        assert master_schema_csn != consumer_schema_csn
+
+    # Check the error log of the supplier does not contain an error
+    # This message may happen during the learning phase
+    regex = re.compile("must not be overwritten \(set replication log for additional info\)")
+    res = pattern_errorlog(topology_m1c1.ms["master1"].errorlog_file, regex)
+
+
+@pytest.mark.ds47490
+def test_schema_replication_six(topology_m1c1, schema_replication_init):
+    """Check supplier schema is  again a superset (OC with more MUST), then
+    schema is pushed and there is no message in the error log
+
+    :id: ed57b0cc-6a10-4f89-94ae-9f18542b1954
+    :setup: Master Consumer, check if a warning message is logged in the
+    error log of the supplier and add a test entry to trigger attempt of schema push.
+    :steps:
+        1. Add telenumber to 'consumerNewOCA' on the master
+        2. Push the Schema (no error)
+        3. Check the schemaCSN was NOT updated on the consumer
+        4. Check the error log of the supplier does not contain an error
+        5. Check the startup/final state
+    :expectedresults:
+        1. Operation should be successful
+        2. Operation should be successful
+        3. Operation should be successful
+        4. Operation should be successful
+        5. State at startup
+            - supplier +masterNewOCA     +masterNewOCB     +consumerNewOCA    +masterNewOCC
+                       +must=telexnumber
+            - consumer +masterNewOCA     +masterNewOCB     +consumerNewOCA
+                       +must=telexnumber                   +must=telexnumber
+           Final state
+
+            - supplier +masterNewOCA     +masterNewOCB     +consumerNewOCA    +masterNewOCC
+                       +must=telexnumber                   +must=telexnumber
+            - consumer +masterNewOCA     +masterNewOCB     +consumerNewOCA    +masterNewOCC
+                       +must=telexnumber                   +must=telexnumber
+           Note: replication log is enabled to get more details
+    """
+    _header(topology_m1c1, "Same OC - extra MUST: Schema is pushed - no error")
+
+    # add telenumber to 'consumerNewOCA' on the consumer
+    mod_OC(topology_m1c1.ms["master1"], 1, 'consumerNewOCA', old_must=MUST_OLD, new_must=MUST_NEW, old_may=MAY_OLD,
+           new_may=MAY_OLD)
+
+    trigger_schema_push(topology_m1c1)
+    master_schema_csn = topology_m1c1.ms["master1"].schema.get_schema_csn()
+    consumer_schema_csn = topology_m1c1.cs["consumer1"].schema.get_schema_csn()
+
+    # Check the schemaCSN was NOT updated on the consumer
+    log.debug("test_schema_replication_six master_schema_csn=%s", master_schema_csn)
+    log.debug("ctest_schema_replication_six onsumer_schema_csn=%s", consumer_schema_csn)
+    assert master_schema_csn == consumer_schema_csn
+
+    # Check the error log of the supplier does not contain an error
+    # This message may happen during the learning phase
+    regex = re.compile("must not be overwritten \(set replication log for additional info\)")
+    res = pattern_errorlog(topology_m1c1.ms["master1"].errorlog_file, regex)
+    if res is not None:
+        assert False
+
+
+@pytest.mark.ds47490
+def test_schema_replication_seven(topology_m1c1, schema_replication_init):
+    """Check supplier schema is again a superset (OC with more MAY), then
+    schema is pushed and there is no message in the error log
+
+    :id: 8725055a-b3f8-4d1d-a4d6-bb7dccf644d0
+    :setup: Master Consumer, check if a warning message is logged in the
+    error log of the supplier and add a test entry to trigger attempt of schema push.
+    :steps:
+        1. Add telenumber to 'masterNewOCA' on the master
+        2. Push the Schema (no error)
+        3. Check the schemaCSN was updated on the consumer
+        4. Check the error log of the supplier does not contain an error
+        5. Check the startup/final state
+    :expectedresults:
+        1. Operation should be successful
+        2. Operation should be successful
+        3. Operation should be successful
+        4. Operation should be successful
+        5. State at startup
+            - supplier +masterNewOCA     +masterNewOCB     +consumerNewOCA    +masterNewOCC
+                       +must=telexnumber                   +must=telexnumber
+            - consumer +masterNewOCA     +masterNewOCB     +consumerNewOCA    +masterNewOCC
+                       +must=telexnumber                   +must=telexnumber
+           Final stat
+            - supplier +masterNewOCA     +masterNewOCB     +consumerNewOCA    +masterNewOCC
+                       +must=telexnumber                   +must=telexnumber
+                       +may=postOfficeBox
+            - consumer +masterNewOCA     +masterNewOCB     +consumerNewOCA    +masterNewOCC
+                       +must=telexnumber                   +must=telexnumber
+                       +may=postOfficeBox
+    """
+    _header(topology_m1c1, "Same OC - extra MAY: Schema is pushed - no error")
+
+    mod_OC(topology_m1c1.ms["master1"], 2, 'masterNewOCA', old_must=MUST_NEW, new_must=MUST_NEW, old_may=MAY_OLD,
+           new_may=MAY_NEW)
+
+    trigger_schema_push(topology_m1c1)
+    master_schema_csn = topology_m1c1.ms["master1"].schema.get_schema_csn()
+    consumer_schema_csn = topology_m1c1.cs["consumer1"].schema.get_schema_csn()
+
+    # Check the schemaCSN was updated on the consumer
+    log.debug("test_schema_replication_seven master_schema_csn=%s", master_schema_csn)
+    log.debug("ctest_schema_replication_seven consumer_schema_csn=%s", consumer_schema_csn)
+    assert master_schema_csn == consumer_schema_csn
+
+    # Check the error log of the supplier does not contain an error
+    regex = re.compile("must not be overwritten \(set replication log for additional info\)")
+    res = pattern_errorlog(topology_m1c1.ms["master1"].errorlog_file, regex)
+    if res is not None:
+        assert False
+
+
+@pytest.mark.ds47490
+def test_schema_replication_eight(topology_m1c1, schema_replication_init):
+    """Check consumer schema is a superset (OC with more MAY), then
+    schema is  pushed (fix for 47721) and there is  message in the error log
+
+    :id: 2310d150-a71a-498d-add8-4056beeb58c6
+    :setup: Master Consumer, check if a warning message is logged in the
+    error log of the supplier and add a test entry to trigger attempt of schema push.
+    :steps:
+        1. Add telenumber to 'consumerNewOCA' on the consumer
+        2. Modify OC on the supplier so that its nsSchemaCSN is larger than the consumer
+        3. Push the Schema (no error)
+        4. Check the schemaCSN was updated on the consumer
+        5. Check the error log of the supplier does not contain an error
+        6. Check the startup/final state
+    :expectedresults:
+        1. Operation should be successful
+        2. Operation should be successful
+        3. Operation should be successful
+        4. Operation should be successful
+        5. Operation should be successful
+        6. State at startup
+            - supplier +masterNewOCA     +masterNewOCB     +consumerNewOCA    +masterNewOCC
+                       +must=telexnumber                   +must=telexnumber
+                       +may=postOfficeBox
+            - consumer +masterNewOCA     +masterNewOCB     +consumerNewOCA    +masterNewOCC
+                       +must=telexnumber                   +must=telexnumber
+                       +may=postOfficeBox
+           Final state
+            - supplier +masterNewOCA     +masterNewOCB     +consumerNewOCA    +masterNewOCC
+                       +must=telexnumber                   +must=telexnumber
+                       +may=postOfficeBox                                     +may=postOfficeBox
+            - consumer +masterNewOCA     +masterNewOCB     +consumerNewOCA    +masterNewOCC
+                       +must=telexnumber                   +must=telexnumber
+                       +may=postOfficeBox                  +may=postOfficeBox
+    """
+    _header(topology_m1c1, "Same OC - extra MAY: Schema is pushed (fix for 47721)")
+
+    mod_OC(topology_m1c1.cs["consumer1"], 1, 'consumerNewOCA', old_must=MUST_NEW, new_must=MUST_NEW, old_may=MAY_OLD,
+           new_may=MAY_NEW)
+
+    # modify OC on the supplier so that its nsSchemaCSN is larger than the consumer (wait 2s)
+    time.sleep(2)
+    mod_OC(topology_m1c1.ms["master1"], 4, 'masterNewOCC', old_must=MUST_OLD, new_must=MUST_OLD, old_may=MAY_OLD,
+           new_may=MAY_NEW)
+
+    trigger_schema_push(topology_m1c1)
+    master_schema_csn = topology_m1c1.ms["master1"].schema.get_schema_csn()
+    consumer_schema_csn = topology_m1c1.cs["consumer1"].schema.get_schema_csn()
+
+    # Check the schemaCSN was not updated on the consumer
+    # with 47721, supplier learns the missing definition
+    log.debug("test_schema_replication_eight master_schema_csn=%s", master_schema_csn)
+    log.debug("ctest_schema_replication_eight onsumer_schema_csn=%s", consumer_schema_csn)
+    if support_schema_learning(topology_m1c1):
+        assert master_schema_csn == consumer_schema_csn
+    else:
+        assert master_schema_csn != consumer_schema_csn
+
+    # Check the error log of the supplier does not contain an error
+    # This message may happen during the learning phase
+    regex = re.compile("must not be overwritten \(set replication log for additional info\)")
+    res = pattern_errorlog(topology_m1c1.ms["master1"].errorlog_file, regex)
+
+
+@pytest.mark.ds47490
+def test_schema_replication_nine(topology_m1c1, schema_replication_init):
+    """Check consumer schema is a superset (OC with more MAY), then
+    schema is  not pushed and there is message in the error log
+
+    :id: 851b24c6-b1e0-466f-9714-aa2940fbfeeb
+    :setup: Master Consumer, check if a warning message is logged in the
+    error log of the supplier and add a test entry to trigger attempt of schema push.
+    :steps:
+        1. Add postOfficeBox to 'consumerNewOCA' on the master
+        3. Push the Schema
+        4. Check the schemaCSN was updated on the consumer
+        5. Check the error log of the supplier does contain an error
+        6. Check the startup/final state
+    :expectedresults:
+        1. Operation should be successful
+        2. Operation should be successful
+        3. Operation should be successful
+        4. Operation should be successful
+        5. Operation should be successful
+        6. State at startup
+            - supplier +masterNewOCA     +masterNewOCB     +consumerNewOCA    +masterNewOCC
+                       +must=telexnumber                   +must=telexnumber
+                       +may=postOfficeBox                                     +may=postOfficeBox
+            - consumer +masterNewOCA     +masterNewOCB     +consumerNewOCA    +masterNewOCC
+                       +must=telexnumber                   +must=telexnumber
+                       +may=postOfficeBox                  +may=postOfficeBox
+
+           Final state
+
+            - supplier +masterNewOCA     +masterNewOCB     +consumerNewOCA    +masterNewOCC
+                       +must=telexnumber                   +must=telexnumber
+                       +may=postOfficeBox                  +may=postOfficeBox +may=postOfficeBox
+            - consumer +masterNewOCA     +masterNewOCB     +consumerNewOCA    +masterNewOCC
+                       +must=telexnumber                   +must=telexnumber
+                       +may=postOfficeBox                  +may=postOfficeBox +may=postOfficeBox
+    """
+    _header(topology_m1c1, "Same OC - extra MAY: Schema is pushed - no error")
+
+    mod_OC(topology_m1c1.ms["master1"], 1, 'consumerNewOCA', old_must=MUST_NEW, new_must=MUST_NEW, old_may=MAY_OLD,
+           new_may=MAY_NEW)
+
+    trigger_schema_push(topology_m1c1)
+    master_schema_csn = topology_m1c1.ms["master1"].schema.get_schema_csn()
+    consumer_schema_csn = topology_m1c1.cs["consumer1"].schema.get_schema_csn()
+
+    # Check the schemaCSN was updated on the consumer
+    log.debug("test_schema_replication_nine master_schema_csn=%s", master_schema_csn)
+    log.debug("ctest_schema_replication_nine onsumer_schema_csn=%s", consumer_schema_csn)
+    assert master_schema_csn == consumer_schema_csn
+
+    # Check the error log of the supplier does not contain an error
+    regex = re.compile("must not be overwritten \(set replication log for additional info\)")
+    res = pattern_errorlog(topology_m1c1.ms["master1"].errorlog_file, regex)
+    if res is not None:
+        assert False
+
+    log.info('Testcase PASSED')
+
+
+if __name__ == '__main__':
+    # Run isolated
+    # -s for DEBUG mode
+    CURRENT_FILE = os.path.realpath(__file__)
+    pytest.main("-s %s" % CURRENT_FILE)
diff --git a/dirsrvtests/tests/tickets/ticket1347760_test.py b/dirsrvtests/tests/tickets/ticket1347760_test.py
deleted file mode 100644
index 4dc2311..0000000
--- a/dirsrvtests/tests/tickets/ticket1347760_test.py
+++ /dev/null
@@ -1,455 +0,0 @@
-# --- BEGIN COPYRIGHT BLOCK ---
-# Copyright (C) 2016 Red Hat, Inc.
-# All rights reserved.
-#
-# License: GPL (version 3 or any later version).
-# See LICENSE for details.
-# --- END COPYRIGHT BLOCK ---
-#
-from subprocess import Popen
-
-import pytest
-from lib389.paths import Paths
-from lib389.tasks import *
-from lib389.utils import *
-from lib389.topologies import topology_st
-
-from lib389._constants import DN_DM, DEFAULT_SUFFIX, PASSWORD, SERVERID_STANDALONE
-
-logging.getLogger(__name__).setLevel(logging.DEBUG)
-log = logging.getLogger(__name__)
-
-CONFIG_DN = 'cn=config'
-BOU = 'BOU'
-BINDOU = 'ou=%s,%s' % (BOU, DEFAULT_SUFFIX)
-BUID = 'buser123'
-TUID = 'tuser0'
-BINDDN = 'uid=%s,%s' % (BUID, BINDOU)
-BINDPW = BUID
-TESTDN = 'uid=%s,ou=people,%s' % (TUID, DEFAULT_SUFFIX)
-TESTPW = TUID
-BOGUSDN = 'uid=bogus,%s' % DEFAULT_SUFFIX
-BOGUSDN2 = 'uid=bogus,ou=people,%s' % DEFAULT_SUFFIX
-BOGUSSUFFIX = 'uid=bogus,ou=people,dc=bogus'
-GROUPOU = 'ou=groups,%s' % DEFAULT_SUFFIX
-BOGUSOU = 'ou=OU,%s' % DEFAULT_SUFFIX
-
-
-def pattern_accesslog(file, log_pattern):
-    for i in range(5):
-        try:
-            pattern_accesslog.last_pos += 1
-        except AttributeError:
-            pattern_accesslog.last_pos = 0
-
-        found = None
-        file.seek(pattern_accesslog.last_pos)
-
-        # Use a while true iteration because 'for line in file: hit a
-        # python bug that break file.tell()
-        while True:
-            line = file.readline()
-            found = log_pattern.search(line)
-            if ((line == '') or (found)):
-                break
-
-        pattern_accesslog.last_pos = file.tell()
-        if found:
-            return line
-        else:
-            time.sleep(1)
-    return None
-
-
-def check_op_result(server, op, dn, superior, exists, rc):
-    targetdn = dn
-    if op == 'search':
-        if exists:
-            opstr = 'Searching existing entry'
-        else:
-            opstr = 'Searching non-existing entry'
-    elif op == 'add':
-        if exists:
-            opstr = 'Adding existing entry'
-        else:
-            opstr = 'Adding non-existing entry'
-    elif op == 'modify':
-        if exists:
-            opstr = 'Modifying existing entry'
-        else:
-            opstr = 'Modifying non-existing entry'
-    elif op == 'modrdn':
-        if superior is not None:
-            targetdn = superior
-            if exists:
-                opstr = 'Moving to existing superior'
-            else:
-                opstr = 'Moving to non-existing superior'
-        else:
-            if exists:
-                opstr = 'Renaming existing entry'
-            else:
-                opstr = 'Renaming non-existing entry'
-    elif op == 'delete':
-        if exists:
-            opstr = 'Deleting existing entry'
-        else:
-            opstr = 'Deleting non-existing entry'
-
-    if ldap.SUCCESS == rc:
-        expstr = 'be ok'
-    else:
-        expstr = 'fail with %s' % rc.__name__
-
-    log.info('%s %s, which should %s.' % (opstr, targetdn, expstr))
-    time.sleep(1)
-    hit = 0
-    try:
-        if op == 'search':
-            centry = server.search_s(dn, ldap.SCOPE_BASE, 'objectclass=*')
-        elif op == 'add':
-            server.add_s(Entry((dn, {'objectclass': 'top extensibleObject'.split(),
-                                     'cn': 'test entry'})))
-        elif op == 'modify':
-            server.modify_s(dn, [(ldap.MOD_REPLACE, 'description', 'test')])
-        elif op == 'modrdn':
-            if superior is not None:
-                server.rename_s(dn, 'uid=new', newsuperior=superior, delold=1)
-            else:
-                server.rename_s(dn, 'uid=new', delold=1)
-        elif op == 'delete':
-            server.delete_s(dn)
-        else:
-            log.fatal('Unknown operation %s' % op)
-            assert False
-    except ldap.LDAPError as e:
-        hit = 1
-        log.info("Exception (expected): %s" % type(e).__name__)
-        log.info('Desc ' + e.message['desc'])
-        assert isinstance(e, rc)
-        if 'matched' in e.message:
-            log.info('Matched is returned: ' + e.message['matched'])
-            if rc != ldap.NO_SUCH_OBJECT:
-                assert False
-
-    if ldap.SUCCESS == rc:
-        if op == 'search':
-            log.info('Search should return none')
-            assert len(centry) == 0
-    else:
-        if 0 == hit:
-            log.info('Expected to fail with %s, but passed' % rc.__name__)
-            assert False
-
-    log.info('PASSED\n')
-
-
-def test_ticket1347760(topology_st):
-    """
-    Prevent revealing the entry info to whom has no access rights.
-    """
-    log.info('Testing Bug 1347760 - Information disclosure via repeated use of LDAP ADD operation, etc.')
-
-    log.info('Disabling accesslog logbuffering')
-    topology_st.standalone.modify_s(CONFIG_DN, [(ldap.MOD_REPLACE, 'nsslapd-accesslog-logbuffering', 'off')])
-
-    log.info('Bind as {%s,%s}' % (DN_DM, PASSWORD))
-    topology_st.standalone.simple_bind_s(DN_DM, PASSWORD)
-
-    log.info('Adding ou=%s a bind user belongs to.' % BOU)
-    topology_st.standalone.add_s(Entry((BINDOU, {
-        'objectclass': 'top organizationalunit'.split(),
-        'ou': BOU})))
-
-    log.info('Adding a bind user.')
-    topology_st.standalone.add_s(Entry((BINDDN,
-                                        {'objectclass': "top person organizationalPerson inetOrgPerson".split(),
-                                         'cn': 'bind user',
-                                         'sn': 'user',
-                                         'userPassword': BINDPW})))
-
-    log.info('Adding a test user.')
-    topology_st.standalone.add_s(Entry((TESTDN,
-                                        {'objectclass': "top person organizationalPerson inetOrgPerson".split(),
-                                         'cn': 'test user',
-                                         'sn': 'user',
-                                         'userPassword': TESTPW})))
-
-    log.info('Deleting aci in %s.' % DEFAULT_SUFFIX)
-    topology_st.standalone.modify_s(DEFAULT_SUFFIX, [(ldap.MOD_DELETE, 'aci', None)])
-
-    log.info('While binding as DM, acquire an access log path and instance dir')
-    ds_paths = Paths(serverid=topology_st.standalone.serverid,
-                     instance=topology_st.standalone)
-    file_path = ds_paths.access_log
-    inst_dir = ds_paths.inst_dir
-
-    log.info('Bind case 1. the bind user has no rights to read the entry itself, bind should be successful.')
-    log.info('Bind as {%s,%s} who has no access rights.' % (BINDDN, BINDPW))
-    try:
-        topology_st.standalone.simple_bind_s(BINDDN, BINDPW)
-    except ldap.LDAPError as e:
-        log.info('Desc ' + e.message['desc'])
-        assert False
-
-    file_obj = open(file_path, "r")
-    log.info('Access log path: %s' % file_path)
-
-    log.info(
-        'Bind case 2-1. the bind user does not exist, bind should fail with error %s' % ldap.INVALID_CREDENTIALS.__name__)
-    log.info('Bind as {%s,%s} who does not exist.' % (BOGUSDN, 'bogus'))
-    try:
-        topology_st.standalone.simple_bind_s(BOGUSDN, 'bogus')
-    except ldap.LDAPError as e:
-        log.info("Exception (expected): %s" % type(e).__name__)
-        log.info('Desc ' + e.message['desc'])
-        assert isinstance(e, ldap.INVALID_CREDENTIALS)
-        regex = re.compile('No such entry')
-        cause = pattern_accesslog(file_obj, regex)
-        if cause is None:
-            log.fatal('Cause not found - %s' % cause)
-            assert False
-        else:
-            log.info('Cause found - %s' % cause)
-    time.sleep(1)
-
-    log.info(
-        'Bind case 2-2. the bind user\'s suffix does not exist, bind should fail with error %s' % ldap.INVALID_CREDENTIALS.__name__)
-    log.info('Bind as {%s,%s} who does not exist.' % (BOGUSSUFFIX, 'bogus'))
-    with pytest.raises(ldap.INVALID_CREDENTIALS):
-        topology_st.standalone.simple_bind_s(BOGUSSUFFIX, 'bogus')
-    regex = re.compile('No suffix for bind')
-    cause = pattern_accesslog(file_obj, regex)
-    if cause is None:
-        log.fatal('Cause not found - %s' % cause)
-        assert False
-    else:
-        log.info('Cause found - %s' % cause)
-    time.sleep(1)
-
-    log.info(
-        'Bind case 2-3. the bind user\'s password is wrong, bind should fail with error %s' % ldap.INVALID_CREDENTIALS.__name__)
-    log.info('Bind as {%s,%s} who does not exist.' % (BINDDN, 'bogus'))
-    try:
-        topology_st.standalone.simple_bind_s(BINDDN, 'bogus')
-    except ldap.LDAPError as e:
-        log.info("Exception (expected): %s" % type(e).__name__)
-        log.info('Desc ' + e.message['desc'])
-        assert isinstance(e, ldap.INVALID_CREDENTIALS)
-        regex = re.compile('Invalid credentials')
-        cause = pattern_accesslog(file_obj, regex)
-        if cause is None:
-            log.fatal('Cause not found - %s' % cause)
-            assert False
-        else:
-            log.info('Cause found - %s' % cause)
-    time.sleep(1)
-
-    log.info('Adding aci for %s to %s.' % (BINDDN, BINDOU))
-    acival = '(targetattr="*")(version 3.0; acl "%s"; allow(all) userdn = "ldap:///%s";)' % (BUID, BINDDN)
-    log.info('aci: %s' % acival)
-    log.info('Bind as {%s,%s}' % (DN_DM, PASSWORD))
-    topology_st.standalone.simple_bind_s(DN_DM, PASSWORD)
-    topology_st.standalone.modify_s(BINDOU, [(ldap.MOD_ADD, 'aci', acival)])
-    time.sleep(1)
-
-    log.info('Bind case 3. the bind user has the right to read the entry itself, bind should be successful.')
-    log.info('Bind as {%s,%s} which should be ok.\n' % (BINDDN, BINDPW))
-    topology_st.standalone.simple_bind_s(BINDDN, BINDPW)
-
-    log.info('The following operations are against the subtree the bind user %s has no rights.' % BINDDN)
-    # Search
-    exists = True
-    rc = ldap.SUCCESS
-    log.info(
-        'Search case 1. the bind user has no rights to read the search entry, it should return no search results with %s' % rc)
-    check_op_result(topology_st.standalone, 'search', TESTDN, None, exists, rc)
-
-    exists = False
-    rc = ldap.SUCCESS
-    log.info(
-        'Search case 2-1. the search entry does not exist, the search should return no search results with %s' % rc.__name__)
-    check_op_result(topology_st.standalone, 'search', BOGUSDN, None, exists, rc)
-
-    exists = False
-    rc = ldap.SUCCESS
-    log.info(
-        'Search case 2-2. the search entry does not exist, the search should return no search results with %s' % rc.__name__)
-    check_op_result(topology_st.standalone, 'search', BOGUSDN2, None, exists, rc)
-
-    # Add
-    exists = True
-    rc = ldap.INSUFFICIENT_ACCESS
-    log.info(
-        'Add case 1. the bind user has no rights AND the adding entry exists, it should fail with %s' % rc.__name__)
-    check_op_result(topology_st.standalone, 'add', TESTDN, None, exists, rc)
-
-    exists = False
-    rc = ldap.INSUFFICIENT_ACCESS
-    log.info(
-        'Add case 2-1. the bind user has no rights AND the adding entry does not exist, it should fail with %s' % rc.__name__)
-    check_op_result(topology_st.standalone, 'add', BOGUSDN, None, exists, rc)
-
-    exists = False
-    rc = ldap.INSUFFICIENT_ACCESS
-    log.info(
-        'Add case 2-2. the bind user has no rights AND the adding entry does not exist, it should fail with %s' % rc.__name__)
-    check_op_result(topology_st.standalone, 'add', BOGUSDN2, None, exists, rc)
-
-    # Modify
-    exists = True
-    rc = ldap.INSUFFICIENT_ACCESS
-    log.info(
-        'Modify case 1. the bind user has no rights AND the modifying entry exists, it should fail with %s' % rc.__name__)
-    check_op_result(topology_st.standalone, 'modify', TESTDN, None, exists, rc)
-
-    exists = False
-    rc = ldap.INSUFFICIENT_ACCESS
-    log.info(
-        'Modify case 2-1. the bind user has no rights AND the modifying entry does not exist, it should fail with %s' % rc.__name__)
-    check_op_result(topology_st.standalone, 'modify', BOGUSDN, None, exists, rc)
-
-    exists = False
-    rc = ldap.INSUFFICIENT_ACCESS
-    log.info(
-        'Modify case 2-2. the bind user has no rights AND the modifying entry does not exist, it should fail with %s' % rc.__name__)
-    check_op_result(topology_st.standalone, 'modify', BOGUSDN2, None, exists, rc)
-
-    # Modrdn
-    exists = True
-    rc = ldap.INSUFFICIENT_ACCESS
-    log.info(
-        'Modrdn case 1. the bind user has no rights AND the renaming entry exists, it should fail with %s' % rc.__name__)
-    check_op_result(topology_st.standalone, 'modrdn', TESTDN, None, exists, rc)
-
-    exists = False
-    rc = ldap.INSUFFICIENT_ACCESS
-    log.info(
-        'Modrdn case 2-1. the bind user has no rights AND the renaming entry does not exist, it should fail with %s' % rc.__name__)
-    check_op_result(topology_st.standalone, 'modrdn', BOGUSDN, None, exists, rc)
-
-    exists = False
-    rc = ldap.INSUFFICIENT_ACCESS
-    log.info(
-        'Modrdn case 2-2. the bind user has no rights AND the renaming entry does not exist, it should fail with %s' % rc.__name__)
-    check_op_result(topology_st.standalone, 'modrdn', BOGUSDN2, None, exists, rc)
-
-    exists = True
-    rc = ldap.INSUFFICIENT_ACCESS
-    log.info(
-        'Modrdn case 3. the bind user has no rights AND the node moving an entry to exists, it should fail with %s' % rc.__name__)
-    check_op_result(topology_st.standalone, 'modrdn', TESTDN, GROUPOU, exists, rc)
-
-    exists = False
-    rc = ldap.INSUFFICIENT_ACCESS
-    log.info(
-        'Modrdn case 4-1. the bind user has no rights AND the node moving an entry to does not, it should fail with %s' % rc.__name__)
-    check_op_result(topology_st.standalone, 'modrdn', TESTDN, BOGUSOU, exists, rc)
-
-    exists = False
-    rc = ldap.INSUFFICIENT_ACCESS
-    log.info(
-        'Modrdn case 4-2. the bind user has no rights AND the node moving an entry to does not, it should fail with %s' % rc.__name__)
-    check_op_result(topology_st.standalone, 'modrdn', TESTDN, BOGUSOU, exists, rc)
-
-    # Delete
-    exists = True
-    rc = ldap.INSUFFICIENT_ACCESS
-    log.info(
-        'Delete case 1. the bind user has no rights AND the deleting entry exists, it should fail with %s' % rc.__name__)
-    check_op_result(topology_st.standalone, 'delete', TESTDN, None, exists, rc)
-
-    exists = False
-    rc = ldap.INSUFFICIENT_ACCESS
-    log.info(
-        'Delete case 2-1. the bind user has no rights AND the deleting entry does not exist, it should fail with %s' % rc.__name__)
-    check_op_result(topology_st.standalone, 'delete', BOGUSDN, None, exists, rc)
-
-    exists = False
-    rc = ldap.INSUFFICIENT_ACCESS
-    log.info(
-        'Delete case 2-2. the bind user has no rights AND the deleting entry does not exist, it should fail with %s' % rc.__name__)
-    check_op_result(topology_st.standalone, 'delete', BOGUSDN2, None, exists, rc)
-
-    log.info('EXTRA: Check no regressions')
-    log.info('Adding aci for %s to %s.' % (BINDDN, DEFAULT_SUFFIX))
-    acival = '(targetattr="*")(version 3.0; acl "%s-all"; allow(all) userdn = "ldap:///%s";)' % (BUID, BINDDN)
-    log.info('Bind as {%s,%s}' % (DN_DM, PASSWORD))
-    topology_st.standalone.simple_bind_s(DN_DM, PASSWORD)
-    topology_st.standalone.modify_s(DEFAULT_SUFFIX, [(ldap.MOD_ADD, 'aci', acival)])
-    time.sleep(1)
-
-    log.info('Bind as {%s,%s}.' % (BINDDN, BINDPW))
-    try:
-        topology_st.standalone.simple_bind_s(BINDDN, BINDPW)
-    except ldap.LDAPError as e:
-        log.info('Desc ' + e.message['desc'])
-        assert False
-    time.sleep(1)
-
-    exists = False
-    rc = ldap.NO_SUCH_OBJECT
-    log.info('Search case. the search entry does not exist, the search should fail with %s' % rc.__name__)
-    check_op_result(topology_st.standalone, 'search', BOGUSDN2, None, exists, rc)
-    file_obj.close()
-
-    exists = True
-    rc = ldap.ALREADY_EXISTS
-    log.info('Add case. the adding entry already exists, it should fail with %s' % rc.__name__)
-    check_op_result(topology_st.standalone, 'add', TESTDN, None, exists, rc)
-
-    exists = False
-    rc = ldap.NO_SUCH_OBJECT
-    log.info('Modify case. the modifying entry does not exist, it should fail with %s' % rc.__name__)
-    check_op_result(topology_st.standalone, 'modify', BOGUSDN, None, exists, rc)
-
-    exists = False
-    rc = ldap.NO_SUCH_OBJECT
-    log.info('Modrdn case 1. the renaming entry does not exist, it should fail with %s' % rc.__name__)
-    check_op_result(topology_st.standalone, 'modrdn', BOGUSDN, None, exists, rc)
-
-    exists = False
-    rc = ldap.NO_SUCH_OBJECT
-    log.info('Modrdn case 2. the node moving an entry to does not, it should fail with %s' % rc.__name__)
-    check_op_result(topology_st.standalone, 'modrdn', TESTDN, BOGUSOU, exists, rc)
-
-    exists = False
-    rc = ldap.NO_SUCH_OBJECT
-    log.info('Delete case. the deleting entry does not exist, it should fail with %s' % rc.__name__)
-    check_op_result(topology_st.standalone, 'delete', BOGUSDN, None, exists, rc)
-
-    log.info('Inactivate %s' % BINDDN)
-    if ds_paths.version < '1.3':
-        nsinactivate = '%s/ns-inactivate.pl' % inst_dir
-        nsinactivate_cmd = [nsinactivate, '-D', DN_DM, '-w', PASSWORD, '-I', BINDDN]
-    else:
-        nsinactivate = '%s/ns-inactivate.pl' % ds_paths.sbin_dir
-        nsinactivate_cmd = [nsinactivate, '-Z', SERVERID_STANDALONE, '-D', DN_DM, '-w', PASSWORD, '-I', BINDDN]
-    log.info(nsinactivate_cmd)
-    p = Popen(nsinactivate_cmd)
-    assert (p.wait() == 0)
-
-    log.info('Bind as {%s,%s} which should fail with %s.' % (BINDDN, BUID, ldap.UNWILLING_TO_PERFORM.__name__))
-    try:
-        topology_st.standalone.simple_bind_s(BINDDN, BUID)
-    except ldap.LDAPError as e:
-        log.info("Exception (expected): %s" % type(e).__name__)
-        log.info('Desc ' + e.message['desc'])
-        assert isinstance(e, ldap.UNWILLING_TO_PERFORM)
-
-    log.info('Bind as {%s,%s} which should fail with %s.' % (BINDDN, 'bogus', ldap.UNWILLING_TO_PERFORM.__name__))
-    try:
-        topology_st.standalone.simple_bind_s(BINDDN, 'bogus')
-    except ldap.LDAPError as e:
-        log.info("Exception (expected): %s" % type(e).__name__)
-        log.info('Desc ' + e.message['desc'])
-        assert isinstance(e, ldap.UNWILLING_TO_PERFORM)
-
-    log.info('SUCCESS')
-
-
-if __name__ == '__main__':
-    # Run isolated
-    # -s for DEBUG mode
-    CURRENT_FILE = os.path.realpath(__file__)
-    pytest.main("-s %s" % CURRENT_FILE)
diff --git a/dirsrvtests/tests/tickets/ticket47431_test.py b/dirsrvtests/tests/tickets/ticket47431_test.py
deleted file mode 100644
index d45346b..0000000
--- a/dirsrvtests/tests/tickets/ticket47431_test.py
+++ /dev/null
@@ -1,208 +0,0 @@
-# --- BEGIN COPYRIGHT BLOCK ---
-# Copyright (C) 2016 Red Hat, Inc.
-# All rights reserved.
-#
-# License: GPL (version 3 or any later version).
-# See LICENSE for details.
-# --- END COPYRIGHT BLOCK ---
-#
-import pytest
-from lib389.tasks import *
-from lib389.utils import *
-from lib389.topologies import topology_st
-
-from lib389._constants import DEFAULT_SUFFIX, DN_PLUGIN, SUFFIX, PLUGIN_7_BIT_CHECK
-
-# Skip on older versions
-pytestmark = pytest.mark.skipif(ds_is_older('1.3'), reason="Not implemented")
-
-logging.getLogger(__name__).setLevel(logging.DEBUG)
-log = logging.getLogger(__name__)
-
-DN_7BITPLUGIN = "cn=7-bit check,%s" % DN_PLUGIN
-ATTRS = ["uid", "mail", "userpassword", ",", SUFFIX, None]
-
-
-def test_ticket47431_0(topology_st):
-    '''
-    Enable 7 bit plugin
-    '''
-    log.info("Ticket 47431 - 0: Enable 7bit plugin...")
-    topology_st.standalone.plugins.enable(name=PLUGIN_7_BIT_CHECK)
-
-def test_ticket47431_1(topology_st):
-    '''
-    nsslapd-pluginarg0: uid
-    nsslapd-pluginarg1: mail
-    nsslapd-pluginarg2: userpassword <== repeat 27 times
-    nsslapd-pluginarg3: ,
-    nsslapd-pluginarg4: dc=example,dc=com
-
-    The duplicated values are removed by str2entry_dupcheck as follows:
-    [..] - str2entry_dupcheck: 27 duplicate values for attribute type nsslapd-pluginarg2
-           detected in entry cn=7-bit check,cn=plugins,cn=config. Extra values ignored.
-    '''
-
-    log.info("Ticket 47431 - 1: Check 26 duplicate values are treated as one...")
-    expected = "str2entry_dupcheck.* duplicate values for attribute type nsslapd-pluginarg2 detected in entry cn=7-bit check,cn=plugins,cn=config."
-
-    log.debug('modify_s %s' % DN_7BITPLUGIN)
-    try:
-        topology_st.standalone.modify_s(DN_7BITPLUGIN,
-                                        [(ldap.MOD_REPLACE, 'nsslapd-pluginarg0', "uid"),
-                                         (ldap.MOD_REPLACE, 'nsslapd-pluginarg1', "mail"),
-                                         (ldap.MOD_REPLACE, 'nsslapd-pluginarg2', "userpassword"),
-                                         (ldap.MOD_REPLACE, 'nsslapd-pluginarg3', ","),
-                                         (ldap.MOD_REPLACE, 'nsslapd-pluginarg4', SUFFIX)])
-    except ValueError:
-        log.error('modify failed: Some problem occured with a value that was provided')
-        assert False
-
-    arg2 = "nsslapd-pluginarg2: userpassword"
-    topology_st.standalone.stop()
-    dse_ldif = topology_st.standalone.confdir + '/dse.ldif'
-    os.system('mv %s %s.47431' % (dse_ldif, dse_ldif))
-    os.system(
-        'sed -e "s/\\(%s\\)/\\1\\n\\1\\n\\1\\n\\1\\n\\1\\n\\1\\n\\1\\n\\1\\n\\1\\n\\1\\n\\1\\n\\1\\n\\1\\n\\1\\n\\1\\n\\1\\n\\1\\n\\1\\n\\1\\n\\1\\n\\1\\n\\1\\n\\1\\n\\1\\n\\1\\n\\1\\n\\1/" %s.47431 > %s' % (
-        arg2, dse_ldif, dse_ldif))
-    topology_st.standalone.start()
-
-    cmdline = 'egrep -i "%s" %s' % (expected, topology_st.standalone.errlog)
-    p = os.popen(cmdline, "r")
-    line = p.readline()
-    if line == "":
-        log.error('Expected error "%s" not logged in %s' % (expected, topology_st.standalone.errlog))
-        assert False
-    else:
-        log.debug('line: %s' % line)
-        log.info('Expected error "%s" logged in %s' % (expected, topology_st.standalone.errlog))
-
-    log.info("Ticket 47431 - 1: done")
-
-
-def test_ticket47431_2(topology_st):
-    '''
-    nsslapd-pluginarg0: uid
-    nsslapd-pluginarg0: mail
-    nsslapd-pluginarg1: userpassword
-    nsslapd-pluginarg2: ,
-    nsslapd-pluginarg3: dc=example,dc=com
-    ==>
-    nsslapd-pluginarg0: uid
-    nsslapd-pluginarg1: mail
-    nsslapd-pluginarg2: userpassword
-    nsslapd-pluginarg3: ,
-    nsslapd-pluginarg4: dc=example,dc=com
-    Should be logged in error log:
-    [..] NS7bitAttr_Init - 0: uid
-    [..] NS7bitAttr_Init - 1: userpassword
-    [..] NS7bitAttr_Init - 2: mail
-    [..] NS7bitAttr_Init - 3: ,
-    [..] NS7bitAttr_Init - 4: dc=example,dc=com
-    '''
-
-    log.info("Ticket 47431 - 2: Check two values belonging to one arg is fixed...")
-
-    try:
-        topology_st.standalone.modify_s(DN_7BITPLUGIN,
-                                        [(ldap.MOD_REPLACE, 'nsslapd-pluginarg0', "uid"),
-                                         (ldap.MOD_ADD, 'nsslapd-pluginarg0', "mail"),
-                                         (ldap.MOD_REPLACE, 'nsslapd-pluginarg1', "userpassword"),
-                                         (ldap.MOD_REPLACE, 'nsslapd-pluginarg2', ","),
-                                         (ldap.MOD_REPLACE, 'nsslapd-pluginarg3', SUFFIX),
-                                         (ldap.MOD_DELETE, 'nsslapd-pluginarg4', None)])
-    except ValueError:
-        log.error('modify failed: Some problem occured with a value that was provided')
-        assert False
-
-    # PLUGIN LOG LEVEL
-    topology_st.standalone.modify_s(DN_CONFIG, [(ldap.MOD_REPLACE, 'nsslapd-errorlog-level', '65536')])
-
-    topology_st.standalone.restart()
-
-    cmdline = 'egrep -i %s %s' % ("NS7bitAttr_Init", topology_st.standalone.errlog)
-    p = os.popen(cmdline, "r")
-    i = 0
-    while ATTRS[i]:
-        line = p.readline()
-        log.debug('line - %s' % line)
-        log.debug('ATTRS[%d] %s' % (i, ATTRS[i]))
-        if line == "":
-            break
-        elif line.find(ATTRS[i]) >= 0:
-            log.debug('%s was logged' % ATTRS[i])
-        else:
-            log.error('%s was not logged.' % ATTRS[i])
-            assert False
-        i = i + 1
-
-    log.info("Ticket 47431 - 2: done")
-
-
-def test_ticket47431_3(topology_st):
-    '''
-    nsslapd-pluginarg1: uid
-    nsslapd-pluginarg3: mail
-    nsslapd-pluginarg5: userpassword
-    nsslapd-pluginarg7: ,
-    nsslapd-pluginarg9: dc=example,dc=com
-    ==>
-    nsslapd-pluginarg0: uid
-    nsslapd-pluginarg1: mail
-    nsslapd-pluginarg2: userpassword
-    nsslapd-pluginarg3: ,
-    nsslapd-pluginarg4: dc=example,dc=com
-    Should be logged in error log:
-    [..] NS7bitAttr_Init - 0: uid
-    [..] NS7bitAttr_Init - 1: userpassword
-    [..] NS7bitAttr_Init - 2: mail
-    [..] NS7bitAttr_Init - 3: ,
-    [..] NS7bitAttr_Init - 4: dc=example,dc=com
-    '''
-
-    log.info("Ticket 47431 - 3: Check missing args are fixed...")
-
-    try:
-        topology_st.standalone.modify_s(DN_7BITPLUGIN,
-                                        [(ldap.MOD_DELETE, 'nsslapd-pluginarg0', None),
-                                         (ldap.MOD_REPLACE, 'nsslapd-pluginarg1', "uid"),
-                                         (ldap.MOD_DELETE, 'nsslapd-pluginarg2', None),
-                                         (ldap.MOD_REPLACE, 'nsslapd-pluginarg3', "mail"),
-                                         (ldap.MOD_REPLACE, 'nsslapd-pluginarg5', "userpassword"),
-                                         (ldap.MOD_REPLACE, 'nsslapd-pluginarg7', ","),
-                                         (ldap.MOD_REPLACE, 'nsslapd-pluginarg9', SUFFIX)])
-    except ValueError:
-        log.error('modify failed: Some problem occured with a value that was provided')
-        assert False
-
-    # PLUGIN LOG LEVEL
-    topology_st.standalone.modify_s(DN_CONFIG, [(ldap.MOD_REPLACE, 'nsslapd-errorlog-level', '65536')])
-
-    topology_st.standalone.stop()
-    os.system('mv %s %s.47431' % (topology_st.standalone.errlog, topology_st.standalone.errlog))
-    os.system('touch %s' % (topology_st.standalone.errlog))
-    topology_st.standalone.start()
-
-    cmdline = 'egrep -i %s %s' % ("NS7bitAttr_Init", topology_st.standalone.errlog)
-    p = os.popen(cmdline, "r")
-    i = 0
-    while ATTRS[i]:
-        line = p.readline()
-        if line == "":
-            break
-        elif line.find(ATTRS[i]) >= 0:
-            log.debug('%s was logged' % ATTRS[i])
-        else:
-            log.error('%s was not logged.' % ATTRS[i])
-            assert False
-        i = i + 1
-
-    log.info("Ticket 47431 - 3: done")
-    log.info('Test complete')
-
-
-if __name__ == '__main__':
-    # Run isolated
-    # -s for DEBUG mode
-    CURRENT_FILE = os.path.realpath(__file__)
-    pytest.main("-s %s" % CURRENT_FILE)
diff --git a/dirsrvtests/tests/tickets/ticket47490_test.py b/dirsrvtests/tests/tickets/ticket47490_test.py
deleted file mode 100644
index df57aab..0000000
--- a/dirsrvtests/tests/tickets/ticket47490_test.py
+++ /dev/null
@@ -1,582 +0,0 @@
-# --- BEGIN COPYRIGHT BLOCK ---
-# Copyright (C) 2016 Red Hat, Inc.
-# All rights reserved.
-#
-# License: GPL (version 3 or any later version).
-# See LICENSE for details.
-# --- END COPYRIGHT BLOCK ---
-#
-'''
-Created on Nov 7, 2013
-
-@author: tbordaz
-'''
-import logging
-import re
-import time
-
-import ldap
-import pytest
-from lib389 import Entry
-from lib389._constants import *
-from lib389.topologies import topology_m1c1
-
-from lib389.utils import *
-
-# Skip on older versions
-pytestmark = pytest.mark.skipif(ds_is_older('1.3'), reason="Not implemented")
-logging.getLogger(__name__).setLevel(logging.DEBUG)
-log = logging.getLogger(__name__)
-
-TEST_REPL_DN = "cn=test_repl, %s" % SUFFIX
-ENTRY_DN = "cn=test_entry, %s" % SUFFIX
-MUST_OLD = "(postalAddress $ preferredLocale)"
-MUST_NEW = "(postalAddress $ preferredLocale $ telexNumber)"
-MAY_OLD = "(postalCode $ street)"
-MAY_NEW = "(postalCode $ street $ postOfficeBox)"
-
-
-def _header(topology_m1c1, label):
-    topology_m1c1.ms["master1"].log.info("\n\n###############################################")
-    topology_m1c1.ms["master1"].log.info("#######")
-    topology_m1c1.ms["master1"].log.info("####### %s" % label)
-    topology_m1c1.ms["master1"].log.info("#######")
-    topology_m1c1.ms["master1"].log.info("###################################################")
-
-
-def pattern_errorlog(file, log_pattern):
-    try:
-        pattern_errorlog.last_pos += 1
-    except AttributeError:
-        pattern_errorlog.last_pos = 0
-
-    found = None
-    log.debug("_pattern_errorlog: start at offset %d" % pattern_errorlog.last_pos)
-    file.seek(pattern_errorlog.last_pos)
-
-    # Use a while true iteration because 'for line in file: hit a
-    # python bug that break file.tell()
-    while True:
-        line = file.readline()
-        log.debug("_pattern_errorlog: [%d] %s" % (file.tell(), line))
-        found = log_pattern.search(line)
-        if ((line == '') or (found)):
-            break
-
-    log.debug("_pattern_errorlog: end at offset %d" % file.tell())
-    pattern_errorlog.last_pos = file.tell()
-    return found
-
-
-def _oc_definition(oid_ext, name, must=None, may=None):
-    oid = "1.2.3.4.5.6.7.8.9.10.%d" % oid_ext
-    desc = 'To test ticket 47490'
-    sup = 'person'
-    if not must:
-        must = MUST_OLD
-    if not may:
-        may = MAY_OLD
-
-    new_oc = "( %s  NAME '%s' DESC '%s' SUP %s AUXILIARY MUST %s MAY %s )" % (oid, name, desc, sup, must, may)
-    return new_oc
-
-
-def add_OC(instance, oid_ext, name):
-    new_oc = _oc_definition(oid_ext, name)
-    instance.schema.add_schema('objectClasses', new_oc)
-
-
-def mod_OC(instance, oid_ext, name, old_must=None, old_may=None, new_must=None, new_may=None):
-    old_oc = _oc_definition(oid_ext, name, old_must, old_may)
-    new_oc = _oc_definition(oid_ext, name, new_must, new_may)
-    instance.schema.del_schema('objectClasses', old_oc)
-    instance.schema.add_schema('objectClasses', new_oc)
-
-
-def support_schema_learning(topology_m1c1):
-    """
-    with https://fedorahosted.org/389/ticket/47721, the supplier and consumer can learn
-    schema definitions when a replication occurs.
-    Before that ticket: replication of the schema fails requiring administrative operation
-    In the test the schemaCSN (master consumer) differs
-
-    After that ticket: replication of the schema succeeds (after an initial phase of learning)
-    In the test the schema CSN (master consumer) are in sync
-
-    This function returns True if 47721 is fixed in the current release
-    False else
-    """
-    ent = topology_m1c1.cs["consumer1"].getEntry(DN_CONFIG, ldap.SCOPE_BASE, "(cn=config)", ['nsslapd-versionstring'])
-    if ent.hasAttr('nsslapd-versionstring'):
-        val = ent.getValue('nsslapd-versionstring')
-        version = val.split('/')[1].split('.')  # something like ['1', '3', '1', '23', 'final_fix']
-        major = int(version[0])
-        minor = int(version[1])
-        if major > 1:
-            return True
-        if minor > 3:
-            # version is 1.4 or after
-            return True
-        if minor == 3:
-            if version[2].isdigit():
-                if int(version[2]) >= 3:
-                    return True
-        return False
-
-
-def trigger_update(topology_m1c1):
-    """
-        It triggers an update on the supplier. This will start a replication
-        session and a schema push
-    """
-    try:
-        trigger_update.value += 1
-    except AttributeError:
-        trigger_update.value = 1
-    replace = [(ldap.MOD_REPLACE, 'telephonenumber', str(trigger_update.value))]
-    topology_m1c1.ms["master1"].modify_s(ENTRY_DN, replace)
-
-    # wait 10 seconds that the update is replicated
-    loop = 0
-    while loop <= 10:
-        try:
-            ent = topology_m1c1.cs["consumer1"].getEntry(ENTRY_DN, ldap.SCOPE_BASE, "(objectclass=*)",
-                                                         ['telephonenumber'])
-            val = ent.telephonenumber or "0"
-            if int(val) == trigger_update.value:
-                return
-            # the expected value is not yet replicated. try again
-            time.sleep(1)
-            loop += 1
-            log.debug("trigger_update: receive %s (expected %d)" % (val, trigger_update.value))
-        except ldap.NO_SUCH_OBJECT:
-            time.sleep(1)
-            loop += 1
-
-
-def trigger_schema_push(topology_m1c1):
-    '''
-    Trigger update to create a replication session.
-    In case of 47721 is fixed and the replica needs to learn the missing definition, then
-    the first replication session learn the definition and the second replication session
-    push the schema (and the schemaCSN.
-    This is why there is two updates and replica agreement is stopped/start (to create a second session)
-    '''
-    agreements = topology_m1c1.ms["master1"].agreement.list(suffix=SUFFIX,
-                                                            consumer_host=topology_m1c1.cs["consumer1"].host,
-                                                            consumer_port=topology_m1c1.cs["consumer1"].port)
-    assert (len(agreements) == 1)
-    ra = agreements[0]
-    trigger_update(topology_m1c1)
-    topology_m1c1.ms["master1"].agreement.pause(ra.dn)
-    topology_m1c1.ms["master1"].agreement.resume(ra.dn)
-    trigger_update(topology_m1c1)
-
-
-def test_ticket47490_init(topology_m1c1):
-    """
-        Initialize the test environment
-    """
-    log.debug("test_ticket47490_init topology_m1c1 %r (master %r, consumer %r" % (
-    topology_m1c1, topology_m1c1.ms["master1"], topology_m1c1.cs["consumer1"]))
-    # the test case will check if a warning message is logged in the
-    # error log of the supplier
-    topology_m1c1.ms["master1"].errorlog_file = open(topology_m1c1.ms["master1"].errlog, "r")
-
-    # This entry will be used to trigger attempt of schema push
-    topology_m1c1.ms["master1"].add_s(Entry((ENTRY_DN, {
-        'objectclass': "top person".split(),
-        'sn': 'test_entry',
-        'cn': 'test_entry'})))
-
-
-def test_ticket47490_one(topology_m1c1):
-    """
-        Summary: Extra OC Schema is pushed - no error
-
-        If supplier schema is a superset (one extra OC) of consumer schema, then
-        schema is pushed and there is no message in the error log
-        State at startup:
-            - supplier default schema
-            - consumer default schema
-        Final state
-            - supplier +masterNewOCA
-            - consumer +masterNewOCA
-
-    """
-    _header(topology_m1c1, "Extra OC Schema is pushed - no error")
-
-    log.debug("test_ticket47490_one topology_m1c1 %r (master %r, consumer %r" % (
-    topology_m1c1, topology_m1c1.ms["master1"], topology_m1c1.cs["consumer1"]))
-    # update the schema of the supplier so that it is a superset of
-    # consumer. Schema should be pushed
-    add_OC(topology_m1c1.ms["master1"], 2, 'masterNewOCA')
-
-    trigger_schema_push(topology_m1c1)
-    master_schema_csn = topology_m1c1.ms["master1"].schema.get_schema_csn()
-    consumer_schema_csn = topology_m1c1.cs["consumer1"].schema.get_schema_csn()
-
-    # Check the schemaCSN was updated on the consumer
-    log.debug("test_ticket47490_one master_schema_csn=%s", master_schema_csn)
-    log.debug("ctest_ticket47490_one onsumer_schema_csn=%s", consumer_schema_csn)
-    assert master_schema_csn == consumer_schema_csn
-
-    # Check the error log of the supplier does not contain an error
-    regex = re.compile("must not be overwritten \(set replication log for additional info\)")
-    res = pattern_errorlog(topology_m1c1.ms["master1"].errorlog_file, regex)
-    if res is not None:
-        assert False
-
-
-def test_ticket47490_two(topology_m1c1):
-    """
-        Summary: Extra OC Schema is pushed - (ticket 47721 allows to learn missing def)
-
-        If consumer schema is a superset (one extra OC) of supplier schema, then
-        schema is pushed and there is a message in the error log
-        State at startup
-            - supplier +masterNewOCA
-            - consumer +masterNewOCA
-        Final state
-            - supplier +masterNewOCA +masterNewOCB
-            - consumer +masterNewOCA               +consumerNewOCA
-
-    """
-
-    _header(topology_m1c1, "Extra OC Schema is pushed - (ticket 47721 allows to learn missing def)")
-
-    # add this OC on consumer. Supplier will no push the schema
-    add_OC(topology_m1c1.cs["consumer1"], 1, 'consumerNewOCA')
-
-    # add a new OC on the supplier so that its nsSchemaCSN is larger than the consumer (wait 2s)
-    time.sleep(2)
-    add_OC(topology_m1c1.ms["master1"], 3, 'masterNewOCB')
-
-    # now push the scheam
-    trigger_schema_push(topology_m1c1)
-    master_schema_csn = topology_m1c1.ms["master1"].schema.get_schema_csn()
-    consumer_schema_csn = topology_m1c1.cs["consumer1"].schema.get_schema_csn()
-
-    # Check the schemaCSN was NOT updated on the consumer
-    # with 47721, supplier learns the missing definition
-    log.debug("test_ticket47490_two master_schema_csn=%s", master_schema_csn)
-    log.debug("test_ticket47490_two consumer_schema_csn=%s", consumer_schema_csn)
-    if support_schema_learning(topology_m1c1):
-        assert master_schema_csn == consumer_schema_csn
-    else:
-        assert master_schema_csn != consumer_schema_csn
-
-    # Check the error log of the supplier does not contain an error
-    # This message may happen during the learning phase
-    regex = re.compile("must not be overwritten \(set replication log for additional info\)")
-    res = pattern_errorlog(topology_m1c1.ms["master1"].errorlog_file, regex)
-
-
-def test_ticket47490_three(topology_m1c1):
-    """
-        Summary: Extra OC Schema is pushed - no error
-
-        If supplier schema is again a superset (one extra OC), then
-        schema is  pushed and there is no message in the error log
-        State at startup
-            - supplier +masterNewOCA +masterNewOCB
-            - consumer +masterNewOCA               +consumerNewOCA
-        Final state
-            - supplier +masterNewOCA +masterNewOCB +consumerNewOCA
-            - consumer +masterNewOCA +masterNewOCB +consumerNewOCA
-
-    """
-    _header(topology_m1c1, "Extra OC Schema is pushed - no error")
-
-    # Do an upate to trigger the schema push attempt
-    # add this OC on consumer. Supplier will no push the schema
-    add_OC(topology_m1c1.ms["master1"], 1, 'consumerNewOCA')
-
-    # now push the scheam
-    trigger_schema_push(topology_m1c1)
-    master_schema_csn = topology_m1c1.ms["master1"].schema.get_schema_csn()
-    consumer_schema_csn = topology_m1c1.cs["consumer1"].schema.get_schema_csn()
-
-    # Check the schemaCSN was NOT updated on the consumer
-    log.debug("test_ticket47490_three master_schema_csn=%s", master_schema_csn)
-    log.debug("test_ticket47490_three consumer_schema_csn=%s", consumer_schema_csn)
-    assert master_schema_csn == consumer_schema_csn
-
-    # Check the error log of the supplier does not contain an error
-    regex = re.compile("must not be overwritten \(set replication log for additional info\)")
-    res = pattern_errorlog(topology_m1c1.ms["master1"].errorlog_file, regex)
-    if res is not None:
-        assert False
-
-
-def test_ticket47490_four(topology_m1c1):
-    """
-        Summary: Same OC - extra MUST: Schema is pushed - no error
-
-        If supplier schema is again a superset (OC with more MUST), then
-        schema is  pushed and there is no message in the error log
-        State at startup
-            - supplier +masterNewOCA +masterNewOCB +consumerNewOCA
-            - consumer +masterNewOCA +masterNewOCB +consumerNewOCA
-        Final state
-            - supplier +masterNewOCA     +masterNewOCB     +consumerNewOCA
-                       +must=telexnumber
-            - consumer +masterNewOCA     +masterNewOCB     +consumerNewOCA
-                       +must=telexnumber
-
-    """
-    _header(topology_m1c1, "Same OC - extra MUST: Schema is pushed - no error")
-
-    mod_OC(topology_m1c1.ms["master1"], 2, 'masterNewOCA', old_must=MUST_OLD, new_must=MUST_NEW, old_may=MAY_OLD,
-           new_may=MAY_OLD)
-
-    trigger_schema_push(topology_m1c1)
-    master_schema_csn = topology_m1c1.ms["master1"].schema.get_schema_csn()
-    consumer_schema_csn = topology_m1c1.cs["consumer1"].schema.get_schema_csn()
-
-    # Check the schemaCSN was updated on the consumer
-    log.debug("test_ticket47490_four master_schema_csn=%s", master_schema_csn)
-    log.debug("ctest_ticket47490_four onsumer_schema_csn=%s", consumer_schema_csn)
-    assert master_schema_csn == consumer_schema_csn
-
-    # Check the error log of the supplier does not contain an error
-    regex = re.compile("must not be overwritten \(set replication log for additional info\)")
-    res = pattern_errorlog(topology_m1c1.ms["master1"].errorlog_file, regex)
-    if res is not None:
-        assert False
-
-
-def test_ticket47490_five(topology_m1c1):
-    """
-        Summary: Same OC - extra MUST: Schema is pushed - (fix for 47721)
-
-        If consumer schema is  a superset (OC with more MUST), then
-        schema is  pushed (fix for 47721) and there is a message in the error log
-        State at startup
-            - supplier +masterNewOCA     +masterNewOCB     +consumerNewOCA
-                       +must=telexnumber
-            - consumer +masterNewOCA     +masterNewOCB     +consumerNewOCA
-                        +must=telexnumber
-        Final state
-            - supplier +masterNewOCA     +masterNewOCB     +consumerNewOCA    +masterNewOCC
-                       +must=telexnumber
-            - consumer +masterNewOCA     +masterNewOCB     +consumerNewOCA
-                       +must=telexnumber                   +must=telexnumber
-
-        Note: replication log is enabled to get more details
-    """
-    _header(topology_m1c1, "Same OC - extra MUST: Schema is pushed - (fix for 47721)")
-
-    # get more detail why it fails
-    topology_m1c1.ms["master1"].enableReplLogging()
-
-    # add telenumber to 'consumerNewOCA' on the consumer
-    mod_OC(topology_m1c1.cs["consumer1"], 1, 'consumerNewOCA', old_must=MUST_OLD, new_must=MUST_NEW, old_may=MAY_OLD,
-           new_may=MAY_OLD)
-    # add a new OC on the supplier so that its nsSchemaCSN is larger than the consumer (wait 2s)
-    time.sleep(2)
-    add_OC(topology_m1c1.ms["master1"], 4, 'masterNewOCC')
-
-    trigger_schema_push(topology_m1c1)
-    master_schema_csn = topology_m1c1.ms["master1"].schema.get_schema_csn()
-    consumer_schema_csn = topology_m1c1.cs["consumer1"].schema.get_schema_csn()
-
-    # Check the schemaCSN was NOT updated on the consumer
-    # with 47721, supplier learns the missing definition
-    log.debug("test_ticket47490_five master_schema_csn=%s", master_schema_csn)
-    log.debug("ctest_ticket47490_five onsumer_schema_csn=%s", consumer_schema_csn)
-    if support_schema_learning(topology_m1c1):
-        assert master_schema_csn == consumer_schema_csn
-    else:
-        assert master_schema_csn != consumer_schema_csn
-
-    # Check the error log of the supplier does not contain an error
-    # This message may happen during the learning phase
-    regex = re.compile("must not be overwritten \(set replication log for additional info\)")
-    res = pattern_errorlog(topology_m1c1.ms["master1"].errorlog_file, regex)
-
-
-def test_ticket47490_six(topology_m1c1):
-    """
-        Summary: Same OC - extra MUST: Schema is pushed - no error
-
-        If supplier schema is  again a superset (OC with more MUST), then
-        schema is  pushed and there is no message in the error log
-        State at startup
-            - supplier +masterNewOCA     +masterNewOCB     +consumerNewOCA    +masterNewOCC
-                       +must=telexnumber
-            - consumer +masterNewOCA     +masterNewOCB     +consumerNewOCA
-                       +must=telexnumber                   +must=telexnumber
-        Final state
-
-            - supplier +masterNewOCA     +masterNewOCB     +consumerNewOCA    +masterNewOCC
-                       +must=telexnumber                   +must=telexnumber
-            - consumer +masterNewOCA     +masterNewOCB     +consumerNewOCA    +masterNewOCC
-                       +must=telexnumber                   +must=telexnumber
-
-        Note: replication log is enabled to get more details
-    """
-    _header(topology_m1c1, "Same OC - extra MUST: Schema is pushed - no error")
-
-    # add telenumber to 'consumerNewOCA' on the consumer
-    mod_OC(topology_m1c1.ms["master1"], 1, 'consumerNewOCA', old_must=MUST_OLD, new_must=MUST_NEW, old_may=MAY_OLD,
-           new_may=MAY_OLD)
-
-    trigger_schema_push(topology_m1c1)
-    master_schema_csn = topology_m1c1.ms["master1"].schema.get_schema_csn()
-    consumer_schema_csn = topology_m1c1.cs["consumer1"].schema.get_schema_csn()
-
-    # Check the schemaCSN was NOT updated on the consumer
-    log.debug("test_ticket47490_six master_schema_csn=%s", master_schema_csn)
-    log.debug("ctest_ticket47490_six onsumer_schema_csn=%s", consumer_schema_csn)
-    assert master_schema_csn == consumer_schema_csn
-
-    # Check the error log of the supplier does not contain an error
-    # This message may happen during the learning phase
-    regex = re.compile("must not be overwritten \(set replication log for additional info\)")
-    res = pattern_errorlog(topology_m1c1.ms["master1"].errorlog_file, regex)
-    if res is not None:
-        assert False
-
-
-def test_ticket47490_seven(topology_m1c1):
-    """
-        Summary: Same OC - extra MAY: Schema is pushed - no error
-
-        If supplier schema is again a superset (OC with more MAY), then
-        schema is  pushed and there is no message in the error log
-        State at startup
-            - supplier +masterNewOCA     +masterNewOCB     +consumerNewOCA    +masterNewOCC
-                       +must=telexnumber                   +must=telexnumber
-            - consumer +masterNewOCA     +masterNewOCB     +consumerNewOCA    +masterNewOCC
-                       +must=telexnumber                   +must=telexnumber
-        Final stat
-            - supplier +masterNewOCA     +masterNewOCB     +consumerNewOCA    +masterNewOCC
-                       +must=telexnumber                   +must=telexnumber
-                       +may=postOfficeBox
-            - consumer +masterNewOCA     +masterNewOCB     +consumerNewOCA    +masterNewOCC
-                       +must=telexnumber                   +must=telexnumber
-                       +may=postOfficeBox
-    """
-    _header(topology_m1c1, "Same OC - extra MAY: Schema is pushed - no error")
-
-    mod_OC(topology_m1c1.ms["master1"], 2, 'masterNewOCA', old_must=MUST_NEW, new_must=MUST_NEW, old_may=MAY_OLD,
-           new_may=MAY_NEW)
-
-    trigger_schema_push(topology_m1c1)
-    master_schema_csn = topology_m1c1.ms["master1"].schema.get_schema_csn()
-    consumer_schema_csn = topology_m1c1.cs["consumer1"].schema.get_schema_csn()
-
-    # Check the schemaCSN was updated on the consumer
-    log.debug("test_ticket47490_seven master_schema_csn=%s", master_schema_csn)
-    log.debug("ctest_ticket47490_seven consumer_schema_csn=%s", consumer_schema_csn)
-    assert master_schema_csn == consumer_schema_csn
-
-    # Check the error log of the supplier does not contain an error
-    regex = re.compile("must not be overwritten \(set replication log for additional info\)")
-    res = pattern_errorlog(topology_m1c1.ms["master1"].errorlog_file, regex)
-    if res is not None:
-        assert False
-
-
-def test_ticket47490_eight(topology_m1c1):
-    """
-        Summary: Same OC - extra MAY: Schema is pushed (fix for 47721)
-
-        If consumer schema is a superset (OC with more MAY), then
-        schema is  pushed (fix for 47721) and there is  message in the error log
-        State at startup
-            - supplier +masterNewOCA     +masterNewOCB     +consumerNewOCA    +masterNewOCC
-                       +must=telexnumber                   +must=telexnumber
-                       +may=postOfficeBox
-            - consumer +masterNewOCA     +masterNewOCB     +consumerNewOCA    +masterNewOCC
-                       +must=telexnumber                   +must=telexnumber
-                       +may=postOfficeBox
-        Final state
-            - supplier +masterNewOCA     +masterNewOCB     +consumerNewOCA    +masterNewOCC
-                       +must=telexnumber                   +must=telexnumber
-                       +may=postOfficeBox                                     +may=postOfficeBox
-            - consumer +masterNewOCA     +masterNewOCB     +consumerNewOCA    +masterNewOCC
-                       +must=telexnumber                   +must=telexnumber
-                       +may=postOfficeBox                  +may=postOfficeBox
-    """
-    _header(topology_m1c1, "Same OC - extra MAY: Schema is pushed (fix for 47721)")
-
-    mod_OC(topology_m1c1.cs["consumer1"], 1, 'consumerNewOCA', old_must=MUST_NEW, new_must=MUST_NEW, old_may=MAY_OLD,
-           new_may=MAY_NEW)
-
-    # modify OC on the supplier so that its nsSchemaCSN is larger than the consumer (wait 2s)
-    time.sleep(2)
-    mod_OC(topology_m1c1.ms["master1"], 4, 'masterNewOCC', old_must=MUST_OLD, new_must=MUST_OLD, old_may=MAY_OLD,
-           new_may=MAY_NEW)
-
-    trigger_schema_push(topology_m1c1)
-    master_schema_csn = topology_m1c1.ms["master1"].schema.get_schema_csn()
-    consumer_schema_csn = topology_m1c1.cs["consumer1"].schema.get_schema_csn()
-
-    # Check the schemaCSN was not updated on the consumer
-    # with 47721, supplier learns the missing definition
-    log.debug("test_ticket47490_eight master_schema_csn=%s", master_schema_csn)
-    log.debug("ctest_ticket47490_eight onsumer_schema_csn=%s", consumer_schema_csn)
-    if support_schema_learning(topology_m1c1):
-        assert master_schema_csn == consumer_schema_csn
-    else:
-        assert master_schema_csn != consumer_schema_csn
-
-    # Check the error log of the supplier does not contain an error
-    # This message may happen during the learning phase
-    regex = re.compile("must not be overwritten \(set replication log for additional info\)")
-    res = pattern_errorlog(topology_m1c1.ms["master1"].errorlog_file, regex)
-
-
-def test_ticket47490_nine(topology_m1c1):
-    """
-        Summary: Same OC - extra MAY: Schema is pushed - no error
-
-        If consumer schema is a superset (OC with more MAY), then
-        schema is  not pushed and there is  message in the error log
-        State at startup
-            - supplier +masterNewOCA     +masterNewOCB     +consumerNewOCA    +masterNewOCC
-                       +must=telexnumber                   +must=telexnumber
-                       +may=postOfficeBox                                     +may=postOfficeBox
-            - consumer +masterNewOCA     +masterNewOCB     +consumerNewOCA    +masterNewOCC
-                       +must=telexnumber                   +must=telexnumber
-                       +may=postOfficeBox                  +may=postOfficeBox
-
-        Final state
-
-            - supplier +masterNewOCA     +masterNewOCB     +consumerNewOCA    +masterNewOCC
-                       +must=telexnumber                   +must=telexnumber
-                       +may=postOfficeBox                  +may=postOfficeBox +may=postOfficeBox
-            - consumer +masterNewOCA     +masterNewOCB     +consumerNewOCA    +masterNewOCC
-                       +must=telexnumber                   +must=telexnumber
-                       +may=postOfficeBox                  +may=postOfficeBox +may=postOfficeBox
-    """
-    _header(topology_m1c1, "Same OC - extra MAY: Schema is pushed - no error")
-
-    mod_OC(topology_m1c1.ms["master1"], 1, 'consumerNewOCA', old_must=MUST_NEW, new_must=MUST_NEW, old_may=MAY_OLD,
-           new_may=MAY_NEW)
-
-    trigger_schema_push(topology_m1c1)
-    master_schema_csn = topology_m1c1.ms["master1"].schema.get_schema_csn()
-    consumer_schema_csn = topology_m1c1.cs["consumer1"].schema.get_schema_csn()
-
-    # Check the schemaCSN was updated on the consumer
-    log.debug("test_ticket47490_nine master_schema_csn=%s", master_schema_csn)
-    log.debug("ctest_ticket47490_nine onsumer_schema_csn=%s", consumer_schema_csn)
-    assert master_schema_csn == consumer_schema_csn
-
-    # Check the error log of the supplier does not contain an error
-    regex = re.compile("must not be overwritten \(set replication log for additional info\)")
-    res = pattern_errorlog(topology_m1c1.ms["master1"].errorlog_file, regex)
-    if res is not None:
-        assert False
-
-    log.info('Testcase PASSED')
-
-
-if __name__ == '__main__':
-    # Run isolated
-    # -s for DEBUG mode
-    CURRENT_FILE = os.path.realpath(__file__)
-    pytest.main("-s %s" % CURRENT_FILE)
diff --git a/dirsrvtests/tests/tickets/ticket47653_test.py b/dirsrvtests/tests/tickets/ticket47653_test.py
deleted file mode 100644
index 241b4d0..0000000
--- a/dirsrvtests/tests/tickets/ticket47653_test.py
+++ /dev/null
@@ -1,311 +0,0 @@
-# --- BEGIN COPYRIGHT BLOCK ---
-# Copyright (C) 2016 Red Hat, Inc.
-# All rights reserved.
-#
-# License: GPL (version 3 or any later version).
-# See LICENSE for details.
-# --- END COPYRIGHT BLOCK ---
-#
-import logging
-
-import ldap
-import pytest
-from lib389 import Entry
-from lib389._constants import *
-from lib389.topologies import topology_st
-
-log = logging.getLogger(__name__)
-
-from lib389.utils import *
-
-# Skip on older versions
-pytestmark = pytest.mark.skipif(ds_is_older('1.3.2'), reason="Not implemented")
-OC_NAME = 'OCticket47653'
-MUST = "(postalAddress $ postalCode)"
-MAY = "(member $ street)"
-
-OTHER_NAME = 'other_entry'
-MAX_OTHERS = 10
-
-BIND_NAME = 'bind_entry'
-BIND_DN = 'cn=%s, %s' % (BIND_NAME, SUFFIX)
-BIND_PW = 'password'
-
-ENTRY_NAME = 'test_entry'
-ENTRY_DN = 'cn=%s, %s' % (ENTRY_NAME, SUFFIX)
-ENTRY_OC = "top person %s" % OC_NAME
-
-
-def _oc_definition(oid_ext, name, must=None, may=None):
-    oid = "1.2.3.4.5.6.7.8.9.10.%d" % oid_ext
-    desc = 'To test ticket 47490'
-    sup = 'person'
-    if not must:
-        must = MUST
-    if not may:
-        may = MAY
-
-    new_oc = "( %s  NAME '%s' DESC '%s' SUP %s AUXILIARY MUST %s MAY %s )" % (oid, name, desc, sup, must, may)
-    return new_oc
-
-
-def test_ticket47653_init(topology_st):
-    """
-        It adds
-           - Objectclass with MAY 'member'
-           - an entry ('bind_entry') with which we bind to test the 'SELFDN' operation
-        It deletes the anonymous aci
-
-    """
-
-    topology_st.standalone.log.info("Add %s that allows 'member' attribute" % OC_NAME)
-    new_oc = _oc_definition(2, OC_NAME, must=MUST, may=MAY)
-    topology_st.standalone.schema.add_schema('objectClasses', new_oc)
-
-    # entry used to bind with
-    topology_st.standalone.log.info("Add %s" % BIND_DN)
-    topology_st.standalone.add_s(Entry((BIND_DN, {
-        'objectclass': "top person".split(),
-        'sn': BIND_NAME,
-        'cn': BIND_NAME,
-        'userpassword': BIND_PW})))
-
-    # enable acl error logging
-    mod = [(ldap.MOD_REPLACE, 'nsslapd-errorlog-level', '128')]
-    topology_st.standalone.modify_s(DN_CONFIG, mod)
-
-    # Remove aci's to start with a clean slate
-    mod = [(ldap.MOD_DELETE, 'aci', None)]
-    topology_st.standalone.modify_s(SUFFIX, mod)
-
-    # add dummy entries
-    for cpt in range(MAX_OTHERS):
-        name = "%s%d" % (OTHER_NAME, cpt)
-        topology_st.standalone.add_s(Entry(("cn=%s,%s" % (name, SUFFIX), {
-            'objectclass': "top person".split(),
-            'sn': name,
-            'cn': name})))
-
-
-def test_ticket47653_add(topology_st):
-    '''
-        It checks that, bound as bind_entry,
-            - we can not ADD an entry without the proper SELFDN aci.
-            - with the proper ACI we can not ADD with 'member' attribute
-            - with the proper ACI and 'member' it succeeds to ADD
-    '''
-    topology_st.standalone.log.info("\n\n######################### ADD ######################\n")
-
-    # bind as bind_entry
-    topology_st.standalone.log.info("Bind as %s" % BIND_DN)
-    topology_st.standalone.simple_bind_s(BIND_DN, BIND_PW)
-
-    # Prepare the entry with multivalued members
-    entry_with_members = Entry(ENTRY_DN)
-    entry_with_members.setValues('objectclass', 'top', 'person', 'OCticket47653')
-    entry_with_members.setValues('sn', ENTRY_NAME)
-    entry_with_members.setValues('cn', ENTRY_NAME)
-    entry_with_members.setValues('postalAddress', 'here')
-    entry_with_members.setValues('postalCode', '1234')
-    members = []
-    for cpt in range(MAX_OTHERS):
-        name = "%s%d" % (OTHER_NAME, cpt)
-        members.append("cn=%s,%s" % (name, SUFFIX))
-    members.append(BIND_DN)
-    entry_with_members.setValues('member', members)
-
-    # Prepare the entry with one member
-    entry_with_member = Entry(ENTRY_DN)
-    entry_with_member.setValues('objectclass', 'top', 'person', 'OCticket47653')
-    entry_with_member.setValues('sn', ENTRY_NAME)
-    entry_with_member.setValues('cn', ENTRY_NAME)
-    entry_with_member.setValues('postalAddress', 'here')
-    entry_with_member.setValues('postalCode', '1234')
-    member = []
-    member.append(BIND_DN)
-    entry_with_member.setValues('member', member)
-
-    # entry to add WITH member being BIND_DN but WITHOUT the ACI -> ldap.INSUFFICIENT_ACCESS
-    try:
-        topology_st.standalone.log.info("Try to add Add  %s (aci is missing): %r" % (ENTRY_DN, entry_with_member))
-
-        topology_st.standalone.add_s(entry_with_member)
-    except Exception as e:
-        topology_st.standalone.log.info("Exception (expected): %s" % type(e).__name__)
-        assert isinstance(e, ldap.INSUFFICIENT_ACCESS)
-
-    # Ok Now add the proper ACI
-    topology_st.standalone.log.info("Bind as %s and add the ADD SELFDN aci" % DN_DM)
-    topology_st.standalone.simple_bind_s(DN_DM, PASSWORD)
-
-    ACI_TARGET = "(target = \"ldap:///cn=*,%s\")" % SUFFIX
-    ACI_TARGETFILTER = "(targetfilter =\"(objectClass=%s)\")" % OC_NAME
-    ACI_ALLOW = "(version 3.0; acl \"SelfDN add\"; allow (add)"
-    ACI_SUBJECT = " userattr = \"member#selfDN\";)"
-    ACI_BODY = ACI_TARGET + ACI_TARGETFILTER + ACI_ALLOW + ACI_SUBJECT
-    mod = [(ldap.MOD_ADD, 'aci', ACI_BODY)]
-    topology_st.standalone.modify_s(SUFFIX, mod)
-
-    # bind as bind_entry
-    topology_st.standalone.log.info("Bind as %s" % BIND_DN)
-    topology_st.standalone.simple_bind_s(BIND_DN, BIND_PW)
-
-    # entry to add WITHOUT member and WITH the ACI -> ldap.INSUFFICIENT_ACCESS
-    try:
-        topology_st.standalone.log.info("Try to add Add  %s (member is missing)" % ENTRY_DN)
-        topology_st.standalone.add_s(Entry((ENTRY_DN, {
-            'objectclass': ENTRY_OC.split(),
-            'sn': ENTRY_NAME,
-            'cn': ENTRY_NAME,
-            'postalAddress': 'here',
-            'postalCode': '1234'})))
-    except Exception as e:
-        topology_st.standalone.log.info("Exception (expected): %s" % type(e).__name__)
-        assert isinstance(e, ldap.INSUFFICIENT_ACCESS)
-
-    # entry to add WITH memberS and WITH the ACI -> ldap.INSUFFICIENT_ACCESS
-    # member should contain only one value
-    try:
-        topology_st.standalone.log.info("Try to add Add  %s (with several member values)" % ENTRY_DN)
-        topology_st.standalone.add_s(entry_with_members)
-    except Exception as e:
-        topology_st.standalone.log.info("Exception (expected): %s" % type(e).__name__)
-        assert isinstance(e, ldap.INSUFFICIENT_ACCESS)
-
-    topology_st.standalone.log.info("Try to add Add  %s should be successful" % ENTRY_DN)
-    topology_st.standalone.add_s(entry_with_member)
-
-
-def test_ticket47653_search(topology_st):
-    '''
-        It checks that, bound as bind_entry,
-            - we can not search an entry without the proper SELFDN aci.
-            - adding the ACI, we can search the entry
-    '''
-    topology_st.standalone.log.info("\n\n######################### SEARCH ######################\n")
-    # bind as bind_entry
-    topology_st.standalone.log.info("Bind as %s" % BIND_DN)
-    topology_st.standalone.simple_bind_s(BIND_DN, BIND_PW)
-
-    # entry to search WITH member being BIND_DN but WITHOUT the ACI -> no entry returned
-    topology_st.standalone.log.info("Try to search  %s (aci is missing)" % ENTRY_DN)
-    ents = topology_st.standalone.search_s(ENTRY_DN, ldap.SCOPE_BASE, 'objectclass=*')
-    assert len(ents) == 0
-
-    # Ok Now add the proper ACI
-    topology_st.standalone.log.info("Bind as %s and add the READ/SEARCH SELFDN aci" % DN_DM)
-    topology_st.standalone.simple_bind_s(DN_DM, PASSWORD)
-
-    ACI_TARGET = "(target = \"ldap:///cn=*,%s\")" % SUFFIX
-    ACI_TARGETATTR = "(targetattr = *)"
-    ACI_TARGETFILTER = "(targetfilter =\"(objectClass=%s)\")" % OC_NAME
-    ACI_ALLOW = "(version 3.0; acl \"SelfDN search-read\"; allow (read, search, compare)"
-    ACI_SUBJECT = " userattr = \"member#selfDN\";)"
-    ACI_BODY = ACI_TARGET + ACI_TARGETATTR + ACI_TARGETFILTER + ACI_ALLOW + ACI_SUBJECT
-    mod = [(ldap.MOD_ADD, 'aci', ACI_BODY)]
-    topology_st.standalone.modify_s(SUFFIX, mod)
-
-    # bind as bind_entry
-    topology_st.standalone.log.info("Bind as %s" % BIND_DN)
-    topology_st.standalone.simple_bind_s(BIND_DN, BIND_PW)
-
-    # entry to search with the proper aci
-    topology_st.standalone.log.info("Try to search  %s should be successful" % ENTRY_DN)
-    ents = topology_st.standalone.search_s(ENTRY_DN, ldap.SCOPE_BASE, 'objectclass=*')
-    assert len(ents) == 1
-
-
-def test_ticket47653_modify(topology_st):
-    '''
-        It checks that, bound as bind_entry,
-            - we can not modify an entry without the proper SELFDN aci.
-            - adding the ACI, we can modify the entry
-    '''
-    # bind as bind_entry
-    topology_st.standalone.log.info("Bind as %s" % BIND_DN)
-    topology_st.standalone.simple_bind_s(BIND_DN, BIND_PW)
-
-    topology_st.standalone.log.info("\n\n######################### MODIFY ######################\n")
-
-    # entry to modify WITH member being BIND_DN but WITHOUT the ACI -> ldap.INSUFFICIENT_ACCESS
-    try:
-        topology_st.standalone.log.info("Try to modify  %s (aci is missing)" % ENTRY_DN)
-        mod = [(ldap.MOD_REPLACE, 'postalCode', '9876')]
-        topology_st.standalone.modify_s(ENTRY_DN, mod)
-    except Exception as e:
-        topology_st.standalone.log.info("Exception (expected): %s" % type(e).__name__)
-        assert isinstance(e, ldap.INSUFFICIENT_ACCESS)
-
-    # Ok Now add the proper ACI
-    topology_st.standalone.log.info("Bind as %s and add the WRITE SELFDN aci" % DN_DM)
-    topology_st.standalone.simple_bind_s(DN_DM, PASSWORD)
-
-    ACI_TARGET = "(target = \"ldap:///cn=*,%s\")" % SUFFIX
-    ACI_TARGETATTR = "(targetattr = *)"
-    ACI_TARGETFILTER = "(targetfilter =\"(objectClass=%s)\")" % OC_NAME
-    ACI_ALLOW = "(version 3.0; acl \"SelfDN write\"; allow (write)"
-    ACI_SUBJECT = " userattr = \"member#selfDN\";)"
-    ACI_BODY = ACI_TARGET + ACI_TARGETATTR + ACI_TARGETFILTER + ACI_ALLOW + ACI_SUBJECT
-    mod = [(ldap.MOD_ADD, 'aci', ACI_BODY)]
-    topology_st.standalone.modify_s(SUFFIX, mod)
-
-    # bind as bind_entry
-    topology_st.standalone.log.info("Bind as %s" % BIND_DN)
-    topology_st.standalone.simple_bind_s(BIND_DN, BIND_PW)
-
-    # modify the entry and checks the value
-    topology_st.standalone.log.info("Try to modify  %s. It should succeeds" % ENTRY_DN)
-    mod = [(ldap.MOD_REPLACE, 'postalCode', '1928')]
-    topology_st.standalone.modify_s(ENTRY_DN, mod)
-
-    ents = topology_st.standalone.search_s(ENTRY_DN, ldap.SCOPE_BASE, 'objectclass=*')
-    assert len(ents) == 1
-    assert ents[0].postalCode == '1928'
-
-
-def test_ticket47653_delete(topology_st):
-    '''
-        It checks that, bound as bind_entry,
-            - we can not delete an entry without the proper SELFDN aci.
-            - adding the ACI, we can delete the entry
-    '''
-    topology_st.standalone.log.info("\n\n######################### DELETE ######################\n")
-
-    # bind as bind_entry
-    topology_st.standalone.log.info("Bind as %s" % BIND_DN)
-    topology_st.standalone.simple_bind_s(BIND_DN, BIND_PW)
-
-    # entry to delete WITH member being BIND_DN but WITHOUT the ACI -> ldap.INSUFFICIENT_ACCESS
-    try:
-        topology_st.standalone.log.info("Try to delete  %s (aci is missing)" % ENTRY_DN)
-        topology_st.standalone.delete_s(ENTRY_DN)
-    except Exception as e:
-        topology_st.standalone.log.info("Exception (expected): %s" % type(e).__name__)
-        assert isinstance(e, ldap.INSUFFICIENT_ACCESS)
-
-    # Ok Now add the proper ACI
-    topology_st.standalone.log.info("Bind as %s and add the READ/SEARCH SELFDN aci" % DN_DM)
-    topology_st.standalone.simple_bind_s(DN_DM, PASSWORD)
-
-    ACI_TARGET = "(target = \"ldap:///cn=*,%s\")" % SUFFIX
-    ACI_TARGETFILTER = "(targetfilter =\"(objectClass=%s)\")" % OC_NAME
-    ACI_ALLOW = "(version 3.0; acl \"SelfDN delete\"; allow (delete)"
-    ACI_SUBJECT = " userattr = \"member#selfDN\";)"
-    ACI_BODY = ACI_TARGET + ACI_TARGETFILTER + ACI_ALLOW + ACI_SUBJECT
-    mod = [(ldap.MOD_ADD, 'aci', ACI_BODY)]
-    topology_st.standalone.modify_s(SUFFIX, mod)
-
-    # bind as bind_entry
-    topology_st.standalone.log.info("Bind as %s" % BIND_DN)
-    topology_st.standalone.simple_bind_s(BIND_DN, BIND_PW)
-
-    # entry to search with the proper aci
-    topology_st.standalone.log.info("Try to delete  %s should be successful" % ENTRY_DN)
-    topology_st.standalone.delete_s(ENTRY_DN)
-
-
-if __name__ == '__main__':
-    # Run isolated
-    # -s for DEBUG mode
-    CURRENT_FILE = os.path.realpath(__file__)
-    pytest.main("-s %s" % CURRENT_FILE)
diff --git a/dirsrvtests/tests/tickets/ticket47669_test.py b/dirsrvtests/tests/tickets/ticket47669_test.py
deleted file mode 100644
index 99aa20b..0000000
--- a/dirsrvtests/tests/tickets/ticket47669_test.py
+++ /dev/null
@@ -1,190 +0,0 @@
-# --- BEGIN COPYRIGHT BLOCK ---
-# Copyright (C) 2016 Red Hat, Inc.
-# All rights reserved.
-#
-# License: GPL (version 3 or any later version).
-# See LICENSE for details.
-# --- END COPYRIGHT BLOCK ---
-#
-import logging
-
-import pytest
-from lib389.tasks import *
-from lib389.topologies import topology_st
-
-from lib389._constants import DN_DM, PASSWORD, DEFAULT_SUFFIX
-
-log = logging.getLogger(__name__)
-
-CHANGELOG = 'cn=changelog5,cn=config'
-RETROCHANGELOG = 'cn=Retro Changelog Plugin,cn=plugins,cn=config'
-
-MAXAGE = 'nsslapd-changelogmaxage'
-TRIMINTERVAL = 'nsslapd-changelogtrim-interval'
-COMPACTDBINTERVAL = 'nsslapd-changelogcompactdb-interval'
-
-FILTER = '(cn=*)'
-
-
-def test_ticket47669_init(topology_st):
-    """
-    Add cn=changelog5,cn=config
-    Enable cn=Retro Changelog Plugin,cn=plugins,cn=config
-    """
-    log.info('Testing Ticket 47669 - Test duration syntax in the changelogs')
-
-    # bind as directory manager
-    topology_st.standalone.log.info("Bind as %s" % DN_DM)
-    topology_st.standalone.simple_bind_s(DN_DM, PASSWORD)
-
-    try:
-        changelogdir = os.path.join(os.path.dirname(topology_st.standalone.dbdir), 'changelog')
-        topology_st.standalone.add_s(Entry((CHANGELOG,
-                                            {'objectclass': 'top extensibleObject'.split(),
-                                             'nsslapd-changelogdir': changelogdir})))
-    except ldap.LDAPError as e:
-        log.error('Failed to add ' + CHANGELOG + ': error ' + e.message['desc'])
-        assert False
-
-    try:
-        topology_st.standalone.modify_s(RETROCHANGELOG, [(ldap.MOD_REPLACE, 'nsslapd-pluginEnabled', 'on')])
-    except ldap.LDAPError as e:
-        log.error('Failed to enable ' + RETROCHANGELOG + ': error ' + e.message['desc'])
-        assert False
-
-    # restart the server
-    topology_st.standalone.restart(timeout=10)
-
-
-def add_and_check(topology_st, plugin, attr, val, isvalid):
-    """
-    Helper function to add/replace attr: val and check the added value
-    """
-    if isvalid:
-        log.info('Test %s: %s -- valid' % (attr, val))
-        try:
-            topology_st.standalone.modify_s(plugin, [(ldap.MOD_REPLACE, attr, val)])
-        except ldap.LDAPError as e:
-            log.error('Failed to add ' + attr + ': ' + val + ' to ' + plugin + ': error ' + e.message['desc'])
-            assert False
-    else:
-        log.info('Test %s: %s -- invalid' % (attr, val))
-        if plugin == CHANGELOG:
-            try:
-                topology_st.standalone.modify_s(plugin, [(ldap.MOD_REPLACE, attr, val)])
-            except ldap.LDAPError as e:
-                log.error('Expectedly failed to add ' + attr + ': ' + val +
-                          ' to ' + plugin + ': error ' + e.message['desc'])
-        else:
-            try:
-                topology_st.standalone.modify_s(plugin, [(ldap.MOD_REPLACE, attr, val)])
-            except ldap.LDAPError as e:
-                log.error('Failed to add ' + attr + ': ' + val + ' to ' + plugin + ': error ' + e.message['desc'])
-
-    try:
-        entries = topology_st.standalone.search_s(plugin, ldap.SCOPE_BASE, FILTER, [attr])
-        if isvalid:
-            if not entries[0].hasValue(attr, val):
-                log.fatal('%s does not have expected (%s: %s)' % (plugin, attr, val))
-                assert False
-        else:
-            if plugin == CHANGELOG:
-                if entries[0].hasValue(attr, val):
-                    log.fatal('%s has unexpected (%s: %s)' % (plugin, attr, val))
-                    assert False
-            else:
-                if not entries[0].hasValue(attr, val):
-                    log.fatal('%s does not have expected (%s: %s)' % (plugin, attr, val))
-                    assert False
-    except ldap.LDAPError as e:
-        log.fatal('Unable to search for entry %s: error %s' % (plugin, e.message['desc']))
-        assert False
-
-
-def test_ticket47669_changelog_maxage(topology_st):
-    """
-    Test nsslapd-changelogmaxage in cn=changelog5,cn=config
-    """
-    log.info('1. Test nsslapd-changelogmaxage in cn=changelog5,cn=config')
-
-    # bind as directory manager
-    topology_st.standalone.log.info("Bind as %s" % DN_DM)
-    topology_st.standalone.simple_bind_s(DN_DM, PASSWORD)
-
-    add_and_check(topology_st, CHANGELOG, MAXAGE, '12345', True)
-    add_and_check(topology_st, CHANGELOG, MAXAGE, '10s', True)
-    add_and_check(topology_st, CHANGELOG, MAXAGE, '30M', True)
-    add_and_check(topology_st, CHANGELOG, MAXAGE, '12h', True)
-    add_and_check(topology_st, CHANGELOG, MAXAGE, '2D', True)
-    add_and_check(topology_st, CHANGELOG, MAXAGE, '4w', True)
-    add_and_check(topology_st, CHANGELOG, MAXAGE, '-123', False)
-    add_and_check(topology_st, CHANGELOG, MAXAGE, 'xyz', False)
-
-
-def test_ticket47669_changelog_triminterval(topology_st):
-    """
-    Test nsslapd-changelogtrim-interval in cn=changelog5,cn=config
-    """
-    log.info('2. Test nsslapd-changelogtrim-interval in cn=changelog5,cn=config')
-
-    # bind as directory manager
-    topology_st.standalone.log.info("Bind as %s" % DN_DM)
-    topology_st.standalone.simple_bind_s(DN_DM, PASSWORD)
-
-    add_and_check(topology_st, CHANGELOG, TRIMINTERVAL, '12345', True)
-    add_and_check(topology_st, CHANGELOG, TRIMINTERVAL, '10s', True)
-    add_and_check(topology_st, CHANGELOG, TRIMINTERVAL, '30M', True)
-    add_and_check(topology_st, CHANGELOG, TRIMINTERVAL, '12h', True)
-    add_and_check(topology_st, CHANGELOG, TRIMINTERVAL, '2D', True)
-    add_and_check(topology_st, CHANGELOG, TRIMINTERVAL, '4w', True)
-    add_and_check(topology_st, CHANGELOG, TRIMINTERVAL, '-123', False)
-    add_and_check(topology_st, CHANGELOG, TRIMINTERVAL, 'xyz', False)
-
-
-def test_ticket47669_changelog_compactdbinterval(topology_st):
-    """
-    Test nsslapd-changelogcompactdb-interval in cn=changelog5,cn=config
-    """
-    log.info('3. Test nsslapd-changelogcompactdb-interval in cn=changelog5,cn=config')
-
-    # bind as directory manager
-    topology_st.standalone.log.info("Bind as %s" % DN_DM)
-    topology_st.standalone.simple_bind_s(DN_DM, PASSWORD)
-
-    add_and_check(topology_st, CHANGELOG, COMPACTDBINTERVAL, '12345', True)
-    add_and_check(topology_st, CHANGELOG, COMPACTDBINTERVAL, '10s', True)
-    add_and_check(topology_st, CHANGELOG, COMPACTDBINTERVAL, '30M', True)
-    add_and_check(topology_st, CHANGELOG, COMPACTDBINTERVAL, '12h', True)
-    add_and_check(topology_st, CHANGELOG, COMPACTDBINTERVAL, '2D', True)
-    add_and_check(topology_st, CHANGELOG, COMPACTDBINTERVAL, '4w', True)
-    add_and_check(topology_st, CHANGELOG, COMPACTDBINTERVAL, '-123', False)
-    add_and_check(topology_st, CHANGELOG, COMPACTDBINTERVAL, 'xyz', False)
-
-
-def test_ticket47669_retrochangelog_maxage(topology_st):
-    """
-    Test nsslapd-changelogmaxage in cn=Retro Changelog Plugin,cn=plugins,cn=config
-    """
-    log.info('4. Test nsslapd-changelogmaxage in cn=Retro Changelog Plugin,cn=plugins,cn=config')
-
-    # bind as directory manager
-    topology_st.standalone.log.info("Bind as %s" % DN_DM)
-    topology_st.standalone.simple_bind_s(DN_DM, PASSWORD)
-
-    add_and_check(topology_st, RETROCHANGELOG, MAXAGE, '12345', True)
-    add_and_check(topology_st, RETROCHANGELOG, MAXAGE, '10s', True)
-    add_and_check(topology_st, RETROCHANGELOG, MAXAGE, '30M', True)
-    add_and_check(topology_st, RETROCHANGELOG, MAXAGE, '12h', True)
-    add_and_check(topology_st, RETROCHANGELOG, MAXAGE, '2D', True)
-    add_and_check(topology_st, RETROCHANGELOG, MAXAGE, '4w', True)
-    add_and_check(topology_st, RETROCHANGELOG, MAXAGE, '-123', False)
-    add_and_check(topology_st, RETROCHANGELOG, MAXAGE, 'xyz', False)
-
-    topology_st.standalone.log.info("ticket47669 was successfully verified.")
-
-
-if __name__ == '__main__':
-    # Run isolated
-    # -s for DEBUG mode
-    CURRENT_FILE = os.path.realpath(__file__)
-    pytest.main("-s %s" % CURRENT_FILE)

