From e92a9835b876a8f826d2f2767b07bfdf6184887b Mon Sep 17 00:00:00 2001
From: Simon Pichugin <spichugi@redhat.com>
Date: Wed, 20 Sep 2017 12:01:23 +0200
Subject: [PATCH] Issue 49381 - Refactor numerous suite docstrings - Part 2

Description: We need to have properly formatted and detailed
docstrings in all existing test suites.
Suites that were changed in this commit:
sasl allowed_mechs, basic, password, replication.
Also, fix create test.py tool, create password policy fixture in
syntax test, in replication move get_repl_entries to __init__.py,
move test_double_delete, test_password_repl_error, test_invalid_agmt
from acceptance_test.py to regression_test.py.
Rename plain.py to plain_test.py
and allowed_mechs.py to allowed_mechs_test.py.

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

Reviewed by: ?
---
 dirsrvtests/create_test.py                         |   8 +-
 dirsrvtests/tests/suites/basic/basic_test.py       |   2 +-
 dirsrvtests/tests/suites/password/password_test.py |  17 +-
 dirsrvtests/tests/suites/password/pwdAdmin_test.py | 117 ++++++---
 .../suites/password/pwdPolicy_attribute_test.py    |  61 +++--
 .../password/pwdPolicy_inherit_global_test.py      |  66 ++---
 .../tests/suites/password/pwdPolicy_syntax_test.py | 101 ++++++--
 .../suites/password/pwdPolicy_warning_test.py      | 238 +++++++++---------
 .../suites/password/pwd_lockout_bypass_test.py     |  25 ++
 .../tests/suites/password/pwp_history_test.py      |  38 ++-
 .../tests/suites/password/regression_test.py       |  32 +--
 dirsrvtests/tests/suites/replication/__init__.py   |  18 ++
 .../tests/suites/replication/acceptance_test.py    | 271 +++++++--------------
 .../tests/suites/replication/cleanallruv_test.py   | 227 ++++++++++-------
 .../tests/suites/replication/regression_test.py    | 172 +++++++++++++
 .../tests/suites/replication/single_master_test.py |  41 ++--
 .../tests/suites/replication/tombstone_test.py     |  17 +-
 .../replication/wait_for_async_feature_test.py     |  57 ++++-
 .../{allowed_mechs.py => allowed_mechs_test.py}    |  78 ++++--
 .../tests/suites/sasl/{plain.py => plain_test.py}  |   2 +-
 20 files changed, 1017 insertions(+), 571 deletions(-)
 create mode 100644 dirsrvtests/tests/suites/replication/regression_test.py
 rename dirsrvtests/tests/suites/sasl/{allowed_mechs.py => allowed_mechs_test.py} (64%)
 rename dirsrvtests/tests/suites/sasl/{plain.py => plain_test.py} (99%)

diff --git a/dirsrvtests/create_test.py b/dirsrvtests/create_test.py
index 4902f7b9b..f5f988cb7 100755
--- a/dirsrvtests/create_test.py
+++ b/dirsrvtests/create_test.py
@@ -210,9 +210,10 @@ if len(sys.argv) > 0:
     if my_topology[0]:
         topology_import = 'from lib389.topologies import {} as topo\n'.format(my_topology[1])
     else:
-        topology_import = ''
+        topology_import = 'from lib389.topologies import create_topology\n'
 
     TEST.write('import logging\nimport pytest\nimport os\n')
+    TEST.write('from lib389._constants import *\n')
     TEST.write('{}\n'.format(topology_import))
 
     TEST.write('DEBUGGING = os.getenv("DEBUGGING", default=False)\n')
@@ -220,7 +221,7 @@ if len(sys.argv) > 0:
     TEST.write('    logging.getLogger(__name__).setLevel(logging.DEBUG)\n')
     TEST.write('else:\n')
     TEST.write('    logging.getLogger(__name__).setLevel(logging.INFO)\n')
-    TEST.write('log = logging.getLogger(__name__)\n\n\n')
+    TEST.write('log = logging.getLogger(__name__)\n\n')
 
     # Add topology function for non existing (in lib389/topologies.py) topologies only
     if not my_topology[0]:
@@ -236,7 +237,7 @@ if len(sys.argv) > 0:
             topologies_str += " {} standalone instances".format(instances)
 
         # Write the 'topology function'
-        TEST.write('@pytest.fixture(scope="module")\n')
+        TEST.write('\n@pytest.fixture(scope="module")\n')
         TEST.write('def topo(request):\n')
         TEST.write('    """Create a topology with{}"""\n\n'.format(topologies_str))
         TEST.write('    topology = create_topology({\n')
@@ -255,6 +256,7 @@ if len(sys.argv) > 0:
         TEST.write('    # replicas.test(DEFAULT_SUFFIX, topology.cs["consumer1"])\n')
 
         writeFinalizer()
+        TEST.write('    return topology\n\n')
 
     tc_id = '0'
     while not check_id_uniqueness(tc_id): tc_id = uuid.uuid4()
diff --git a/dirsrvtests/tests/suites/basic/basic_test.py b/dirsrvtests/tests/suites/basic/basic_test.py
index 45988dc7a..40ffde8a3 100644
--- a/dirsrvtests/tests/suites/basic/basic_test.py
+++ b/dirsrvtests/tests/suites/basic/basic_test.py
@@ -580,7 +580,7 @@ def test_basic_referrals(topology_st, import_example_ldif):
     :setup: Standalone instance
 
     :steps:
-         1. Set the referral and the backenidealyd state
+         1. Set the referral and the backend state
          2. Set backend state to referral mode.
          3. Set server to not follow referral.
          4. Search using referral.
diff --git a/dirsrvtests/tests/suites/password/password_test.py b/dirsrvtests/tests/suites/password/password_test.py
index 860192f83..b08c6b0dd 100644
--- a/dirsrvtests/tests/suites/password/password_test.py
+++ b/dirsrvtests/tests/suites/password/password_test.py
@@ -18,9 +18,22 @@ log = logging.getLogger(__name__)
 
 
 def test_password_delete_specific_password(topology_st):
-    """ Delete a specific userpassword, and make sure
+    """Delete a specific userPassword, and make sure
     it is actually deleted from the entry
-    """
+
+    :id: 800f432a-52ab-4661-ac66-a2bdd9b984d6
+    :setup: Standalone instance
+    :steps:
+        1. Add a user with userPassword attribute in cleartext
+        2. Delete the added value of userPassword attribute
+        3. Check if the userPassword attribute is deleted
+        4. Delete the user
+    :expectedresults:
+        1. The user with userPassword in cleartext should be added successfully
+        2. Operation should be successful
+        3. UserPassword should be deleted
+        4. The user should be successfully deleted
+     """
 
     log.info('Running test_password_delete_specific_password...')
 
diff --git a/dirsrvtests/tests/suites/password/pwdAdmin_test.py b/dirsrvtests/tests/suites/password/pwdAdmin_test.py
index b49e10d1a..0d13936de 100644
--- a/dirsrvtests/tests/suites/password/pwdAdmin_test.py
+++ b/dirsrvtests/tests/suites/password/pwdAdmin_test.py
@@ -28,13 +28,16 @@ ENTRY_DN = 'cn=%s,%s' % (ENTRY_NAME, SUFFIX)
 INVALID_PWDS = ('2_Short', 'No_Number', 'N0Special', '{SSHA}bBy8UdtPZwu8uZna9QOYG3Pr41RpIRVDl8wddw==')
 
 
-def test_pwdAdmin_init(topology_st):
-    '''
-    Create our future Password Admin entry, set the password policy, and test
-    that its working
-    '''
+@pytest.fixture(scope="module")
+def password_policy(topology_st):
+    """Set up password policy
+    Create a Password Admin entry;
+    Set up password policy attributes in config;
+    Add an aci to give everyone full access;
+    Test that the setup works
+    """
 
-    log.info('test_pwdAdmin_init: Creating Password Administator entries...')
+    log.info('test_pwdAdmin_init: Creating Password Administrator entries...')
 
     # Add Password Admin 1
     try:
@@ -100,7 +103,7 @@ def test_pwdAdmin_init(topology_st):
     #
     # Bind as the future Password Admin
     #
-    log.info('test_pwdAdmin_init: Bind as the Password Administator (before activating)...')
+    log.info('test_pwdAdmin_init: Bind as the Password Administrator (before activating)...')
     try:
         topology_st.standalone.simple_bind_s(ADMIN_DN, ADMIN_PWD)
     except ldap.LDAPError as e:
@@ -139,19 +142,61 @@ def test_pwdAdmin_init(topology_st):
             assert False
 
 
-def test_pwdAdmin(topology_st):
-    '''
-        Test that password administrators/root DN can
-        bypass password syntax/policy.
-
-        We need to test how passwords are modified in
-        existing entries, and when adding new entries.
-
-        Create the Password Admin entry, but do not set
-        it as an admin yet.  Use the entry to verify invalid
-        passwords are caught.  Then activate the password
-        admin and make sure it can bypass password policy.
-    '''
+def test_pwdAdmin(topology_st, password_policy):
+    """Test that password administrators/root DN can
+    bypass password syntax/policy
+
+    :id: 5ce316d8-88ef-4248-8b63-90736985dad5
+    :setup: Standalone instance, Password Admin entry,
+        Password policy configured as below:
+            nsslapd-pwpolicy-local: on
+            passwordCheckSyntax: on
+            passwordMinCategories: 1
+            passwordMinTokenLength: 1
+            passwordExp: on
+            passwordMinDigits: 1
+            passwordMinSpecials: 1
+    :steps:
+        1. Bind as Root DN
+        2. Set passwordAdminDn to our admin entry DN
+        3. Bind as Password Admin
+        4. Add entries with invalid passwords
+        5. Delete the entries after each pass
+        6. Add the entry for the next round of testing
+        7. Bind as root DN
+        8. Remove passwordAdminDN attribute
+        9. Bind as Password Admin (admin rights are revoked)
+        10. Make invalid password updates
+        11. Bind as root DN to make the update
+        12. Set passwordAdminDn to our admin entry DN
+        13. Bind as Password Admin
+        14. Make the same password updates
+        15. Bind as root DN to make the update
+        16. Set passwordAdminDn to admin group entry
+        17. Bind as admin2
+        18. Make some invalid password updates
+        19. Bind back as Root DN
+    :expectedresults:
+        1. Bind should be successful
+        2. passwordAdminDn should be set successful
+        3. Bind should be successful
+        4. The entries should be successfully added
+        5. The entries should be successfully deleted
+        6. The entry should be successfully added
+        7. Bind should be successful
+        8. passwordAdminDn should be removed successful
+        9. Bind should be successful
+        10. Invalid password updates should fail
+        11. Bind should be successful
+        12. passwordAdminDn should be set successful
+        13. Bind should be successful
+        14. The same password updates should pass now
+        15. Bind should be successful
+        16. passwordAdminDn should be set successful
+        17. Bind should be successful
+        18. The same password updates should pass now
+        19. Bind should be successful
+    """
 
     #
     # Now activate a password administator, bind as root dn to do the config
@@ -160,7 +205,7 @@ def test_pwdAdmin(topology_st):
     log.info('test_pwdAdmin: Activate the Password Administator...')
 
     #
-    # Setup our test entry, and test password policy is working
+    # Get our test entry
     #
     entry = Entry(ENTRY_DN)
     entry.setValues('objectclass', 'top', 'person')
@@ -361,14 +406,28 @@ def test_pwdAdmin(topology_st):
         assert False
 
 
-def test_pwdAdmin_config_validation(topology_st):
-    '''
-    Test config validation:
-
-    - Test adding multiple passwordAdminDN attributes
-    - Test adding invalid values(non-DN's)
-    '''
-    # Add mulitple attributes - one already eists so just try and add as second one
+def test_pwdAdmin_config_validation(topology_st, password_policy):
+    """Check passwordAdminDN for valid and invalid values
+
+    :id: f7049482-41e8-438b-ae18-cdd2612c783a
+    :setup: Standalone instance, Password Admin entry,
+        Password policy configured as below:
+            nsslapd-pwpolicy-local: on
+            passwordCheckSyntax: on
+            passwordMinCategories: 1
+            passwordMinTokenLength: 1
+            passwordExp: on
+            passwordMinDigits: 1
+            passwordMinSpecials: 1
+    :steps:
+        1. Add multiple attributes - one already exists so just try and add the second one
+        2. Set passwordAdminDN attribute to an invalid value (ZZZZZ)
+    :expectedresults:
+        1. The operation should fail
+        2. The operation should fail
+    """
+
+    # Add multiple attributes - one already exists so just try and add the second one
     try:
         topology_st.standalone.modify_s(CONFIG_DN, [(ldap.MOD_ADD, 'passwordAdminDN', ENTRY_DN)])
         log.fatal('test_pwdAdmin_config_validation: Incorrectly was able to add two config attributes')
diff --git a/dirsrvtests/tests/suites/password/pwdPolicy_attribute_test.py b/dirsrvtests/tests/suites/password/pwdPolicy_attribute_test.py
index 9d77c7b71..b3ef61d2d 100644
--- a/dirsrvtests/tests/suites/password/pwdPolicy_attribute_test.py
+++ b/dirsrvtests/tests/suites/password/pwdPolicy_attribute_test.py
@@ -127,19 +127,22 @@ def test_change_pwd(topology_st, test_user, password_policy,
     """Verify that 'passwordChange' attr works as expected
     User should have a priority over a subtree.
 
-    :feature: Password policy
-
-    :setup: Standalone instance, test user,
+    :id: 2c884432-2ba1-4662-8e5d-2cd49f77e5fa
+    :setup: Standalone instance, a test user,
             password policy entries for a user and a subtree
-
-    :steps: 1. Set passwordChange on the user and the subtree
-               to various combinations
-            2. Bind as test user
-            3. Try to change password
-
-    :expectedresults: Subtree/User passwordChange - result
-             off/on, on/on - success
-             on/off, off/off - UNWILLING_TO_PERFORM
+    :steps:
+        1. Set passwordChange on the user and the subtree
+           to various combinations
+        2. Bind as test user
+        3. Try to change password
+        4. Clean up - change the password to default while bound as DM
+    :expectedresults:
+        1. passwordChange should be successfully set
+        2. Bind should be successful
+        3. Subtree/User passwordChange - result, accordingly:
+           off/on, on/on - success;
+           on/off, off/off - UNWILLING_TO_PERFORM
+        4. Operation should be successful
     """
 
     log.info('Set passwordChange to "{}" - {}'.format(subtree_pwchange,
@@ -196,21 +199,27 @@ def test_pwd_min_age(topology_st, test_user, password_policy):
     should not allow the user to change the password within 10 seconds after
     his previous change.
 
-    :ID: 85b98516-8c82-45bd-b9ec-90bd1245e09c
-    :feature: Password policy
-    :setup: Standalone instance, test user,
+    :id: 85b98516-8c82-45bd-b9ec-90bd1245e09c
+    :setup: Standalone instance, a test user,
             password policy entries for a user and a subtree
-    :steps: 1. Set passwordMinAge to 10 on the user pwpolicy entry
-            2. Set passwordMinAge to 10 on the subtree pwpolicy entry
-            3. Set passwordMinAge to 10 on the cn=config entry
-            4. Bind as test user
-            5. Try to change password two times in a row
-            6. Wait 12 seconds
-            7. Try to change password
-    :expectedresults: User should be not allowed to change the password
-             right after previous change - CONSTRAINT_VIOLATION
-             User should be not allowed to change the password
-             after 12 seconds passed
+    :steps:
+        1. Set passwordMinAge to 10 on the user pwpolicy entry
+        2. Set passwordMinAge to 10 on the subtree pwpolicy entry
+        3. Set passwordMinAge to 10 on the cn=config entry
+        4. Bind as test user
+        5. Try to change the password two times in a row
+        6. Wait 12 seconds
+        7. Try to change the password
+        8. Clean up - change the password to default while bound as DM
+    :expectedresults:
+        1. passwordMinAge should be successfully set on the user pwpolicy entry
+        2. passwordMinAge should be successfully set on the subtree pwpolicy entry
+        3. passwordMinAge should be successfully set on the cn=config entry
+        4. Bind should be successful
+        5. The password should be successfully changed
+        6. 12 seconds have passed
+        7. Constraint Violation error should be raised
+        8. Operation should be successful
     """
 
     num_seconds = '10'
diff --git a/dirsrvtests/tests/suites/password/pwdPolicy_inherit_global_test.py b/dirsrvtests/tests/suites/password/pwdPolicy_inherit_global_test.py
index 828a2d3a4..823cfda61 100644
--- a/dirsrvtests/tests/suites/password/pwdPolicy_inherit_global_test.py
+++ b/dirsrvtests/tests/suites/password/pwdPolicy_inherit_global_test.py
@@ -139,25 +139,23 @@ def check_attr_val(topology_st, dn, attr, expected):
                          [('off', 'off'), ('on', 'off'), ('off', 'on')])
 def test_entry_has_no_restrictions(topology_st, password_policy, test_user,
                                    inherit_value, checksyntax_value):
-    """Make sure an entry added to ou=people
-    has no password syntax restrictions when:
-    - 'passwordCheckSyntax' is 'off' for 'nsslapd-pwpolicy-inherit-global'
-    equaled 'off' and 'on'
-    - 'passwordCheckSyntax' is 'on' for  'nsslapd-pwpolicy-inherit-global'
-    equaled 'off'
-
-    :ID: 2f07ff40-76ca-45a9-a556-331c94084945
-    :feature: Password policy
+    """Make sure an entry added to ou=people has no password syntax restrictions
+
+    :id: 2f07ff40-76ca-45a9-a556-331c94084945
     :setup: Standalone instance, test user,
             password policy entries for a subtree
-    :steps: 1. Bind as test user
-            2. Set 'nsslapd-pwpolicy-inherit-global' and
-               'passwordCheckSyntax' accordingly:
-               a) 'off' and 'off'
-               b) 'on' and 'off'
-               c) 'off' and 'on'
-            3. Try to add user with a short password
-    :expectedresults: No exception should occure
+    :steps:
+        1. Bind as test user
+        2. Set 'nsslapd-pwpolicy-inherit-global' and
+           'passwordCheckSyntax' accordingly:
+           'off' and 'off'; 'on' and 'off'; 'off' and 'on'
+        3. Try to add user with a short password
+        4. Cleanup - remove temp user bound as DM
+    :expectedresults:
+        1. Bind should be successful
+        2. Attributes should be successfully set
+        3. No exceptions should occur
+        4. Operation should be successful
     """
 
     log.info('Set {} to {}'.format(ATTR_INHERIT_GLOBAL, inherit_value))
@@ -203,24 +201,30 @@ def test_entry_has_no_restrictions(topology_st, password_policy, test_user,
 
 @pytest.mark.parametrize('container', [DN_CONFIG, PWP_CONTAINER_PEOPLE])
 def test_entry_has_restrictions(topology_st, password_policy, test_user, container):
-    """Set 'nsslapd-pwpolicy-inherit-global: on'
-    and 'passwordCheckSyntax: on'. Make sure that
-    syntax rules work, if set them at both: cn=config and
+    """Set 'nsslapd-pwpolicy-inherit-global: on' and 'passwordCheckSyntax: on'.
+    Make sure that syntax rules work, if set them at both: cn=config and
     ou=people policy container.
 
-    :ID: 4bb0f474-17c1-40f7-aab4-4ddc17d019e8
-    :feature: Password policy
+    :id: 4bb0f474-17c1-40f7-aab4-4ddc17d019e8
     :setup: Standalone instance, test user,
             password policy entries for a subtree
-    :steps: 1. Bind as test user
-            2. Switch 'nsslapd-pwpolicy-inherit-global: on'
-            3. Switch 'passwordCheckSyntax: on'
-            4. Set 'passwordMinLength: 9' to:
-               a) cn=config
-               b) ou=people policy container
-            5. Try to add user with a short password (<9)
-            6. Try to add user with a long password (>9)
-    :expectedresults: User should be rejected
+    :steps:
+        1. Bind as test user
+        2. Switch 'nsslapd-pwpolicy-inherit-global: on'
+        3. Switch 'passwordCheckSyntax: on'
+        4. Set 'passwordMinLength: 9' to:
+           cn=config and ou=people policy container
+        5. Try to add user with a short password (<9)
+        6. Try to add user with a long password (>9)
+        7. Cleanup - remove temp users bound as DM
+    :expectedresults:
+        1. Bind should be successful
+        2. nsslapd-pwpolicy-inherit-global should be successfully set
+        3. passwordCheckSyntax should be successfully set
+        4. passwordMinLength should be successfully set
+        5. User should be rejected
+        6. User should be rejected
+        7. Operation should be successful
     """
 
     log.info('Set {} to {}'.format(ATTR_INHERIT_GLOBAL, 'on'))
diff --git a/dirsrvtests/tests/suites/password/pwdPolicy_syntax_test.py b/dirsrvtests/tests/suites/password/pwdPolicy_syntax_test.py
index 14642333f..5737303c3 100644
--- a/dirsrvtests/tests/suites/password/pwdPolicy_syntax_test.py
+++ b/dirsrvtests/tests/suites/password/pwdPolicy_syntax_test.py
@@ -22,9 +22,21 @@ logging.getLogger(__name__).setLevel(logging.INFO)
 log = logging.getLogger(__name__)
 
 
-def _create_user(inst):
+@pytest.fixture(scope="module")
+def password_policy(topology_st):
+    """Set global password policy"""
+
+    log.info('Enable global password policy. Check for syntax.')
+    topology_st.standalone.config.set('passwordCheckSyntax', 'on')
+    topology_st.standalone.config.set('nsslapd-pwpolicy-local', 'off')
+    topology_st.standalone.config.set('passwordMinCategories', '1')
+
+
+@pytest.fixture(scope="module")
+def test_user(topology_st):
     """Create the test user."""
-    inst.add_s(Entry((
+
+    topology_st.standalone.add_s(Entry((
         USER_DN, {
             'objectClass': 'top account simplesecurityobject'.split(),
             'uid': 'user',
@@ -34,6 +46,7 @@ def _create_user(inst):
 
 def setPolicy(inst, attr, value):
     """Bind as ROot DN, set polcy, and then bind as user"""
+
     try:
         inst.simple_bind_s(DN_DM, PASSWORD)
     except ldap.LDAPError as e:
@@ -117,22 +130,82 @@ def tryPassword(inst, policy_attr, value, reset_value, pw_bad, pw_good, msg):
     setPolicy(inst, policy_attr, reset_value)
 
 
-def test_pwdPolicy_syntax(topology_st):
-    '''
-    Password policy test: Ensure that on a password change, the policy syntax
+def test_basic(topology_st, test_user, password_policy):
+    """Ensure that on a password change, the policy syntax
     is enforced correctly.
-    '''
-
-    # Create a user
-    _create_user(topology_st.standalone)
 
-    # Set the password policy globally
-    topology_st.standalone.config.set('passwordCheckSyntax', 'on')
-    topology_st.standalone.config.set('nsslapd-pwpolicy-local', 'off')
-    topology_st.standalone.config.set('passwordMinCategories', '1')
+    :id: e8de7029-7fa6-4e96-9eb6-4a121f4c8fb3
+    :setup: Standalone instance, a test user,
+            global password policy with:
+            passwordCheckSyntax - on; nsslapd-pwpolicy-local - off;
+            passwordMinCategories - 1
+    :steps:
+        1. Set passwordMinLength to 10 in cn=config
+        2. Set userPassword to 'passwd' in cn=config
+        3. Set userPassword to 'password123' in cn=config
+        4. Set passwordMinLength to 2 in cn=config
+        5. Set passwordMinDigits to 2 in cn=config
+        6. Set userPassword to 'passwd' in cn=config
+        7. Set userPassword to 'password123' in cn=config
+        8. Set passwordMinDigits to 0 in cn=config
+        9. Set passwordMinAlphas to 2 in cn=config
+        10. Set userPassword to 'p123456789' in cn=config
+        11. Set userPassword to 'password123' in cn=config
+        12. Set passwordMinAlphas to 0 in cn=config
+        13. Set passwordMaxRepeats to 2 in cn=config
+        14. Set userPassword to 'password' in cn=config
+        15. Set userPassword to 'password123' in cn=config
+        16. Set passwordMaxRepeats to 0 in cn=config
+        17. Set passwordMinSpecials to 2 in cn=config
+        18. Set userPassword to 'passwd' in cn=config
+        19. Set userPassword to 'password_#$' in cn=config
+        20. Set passwordMinSpecials to 0 in cn=config
+        21. Set passwordMinLowers to 2 in cn=config
+        22. Set userPassword to 'PASSWORD123' in cn=config
+        23. Set userPassword to 'password123' in cn=config
+        24. Set passwordMinLowers to 0 in cn=config
+        25. Set passwordMinUppers to 2 in cn=config
+        26. Set userPassword to 'password' in cn=config
+        27. Set userPassword to 'PASSWORD' in cn=config
+        28. Set passwordMinUppers to 0 in cn=config
+    :expectedresults:
+        1. passwordMinLength should be successfully set
+        2. Password should be rejected because length too short
+        3. Password should be accepted
+        4. passwordMinLength should be successfully set
+        5. passwordMinDigits should be successfully set
+        6. Password should be rejected because
+           it does not contain minimum number of digits
+        7. Password should be accepted
+        8. passwordMinDigits should be successfully set
+        9. passwordMinAlphas should be successfully set
+        10. Password should be rejected because
+            it does not contain minimum number of alphas
+        11. Password should be accepted
+        12. passwordMinAlphas should be successfully set
+        13. passwordMaxRepeats should be successfully set
+        14. Password should be rejected because too many repeating characters
+        15. Password should be accepted
+        16. passwordMaxRepeats should be successfully set
+        17. passwordMinSpecials should be successfully set
+        18. Password should be rejected because
+            it does not contain minimum number of special characters
+        19. Password should be accepted
+        20. passwordMinSpecials should be successfully set
+        21. passwordMinLowers should be successfully set
+        22. Password should be rejected because
+            it does not contain minimum number of lowercase characters
+        23. Password should be accepted
+        24. passwordMinLowers should be successfully set
+        25. passwordMinUppers should be successfully set
+        26. Password should be rejected because
+            it does not contain minimum number of lowercase characters
+        27. Password should be accepted
+        28. passwordMinUppers should be successfully set
+    """
 
     #
-    # Test each syntax catagory
+    # Test each syntax category
     #
 
     # Min Length
diff --git a/dirsrvtests/tests/suites/password/pwdPolicy_warning_test.py b/dirsrvtests/tests/suites/password/pwdPolicy_warning_test.py
index 1b955c66e..10775ff66 100644
--- a/dirsrvtests/tests/suites/password/pwdPolicy_warning_test.py
+++ b/dirsrvtests/tests/suites/password/pwdPolicy_warning_test.py
@@ -238,17 +238,20 @@ def test_different_values(topology_st, value):
     """Try to set passwordSendExpiringTime attribute
     to various values both valid and invalid
 
-    :ID: 3e6d79fb-b4c8-4860-897e-5b207815a75d
-    :feature: Password Expiry Warning Time
-    :setup: Standalone DS instance
-    :steps: 1. Try to set valid and invalid values
-               for passwordSendExpiringTime attribute
-               under cn=config entry
-            2. Run the search command to check the
-               value of passwordSendExpiringTime attribute
-    :expectedresults: 1. Invalid values should be rejected with
-                      an OPERATIONS_ERROR
-                      2. Valid values should be accepted and saved
+    :id: 3e6d79fb-b4c8-4860-897e-5b207815a75d
+    :setup: Standalone instance
+    :steps:
+        1. Try to set passwordSendExpiringTime to 'on' and 'off'
+           under cn=config entry
+        2. Try to set passwordSendExpiringTime to ' ' and 'junk123'
+           under cn=config entry
+        3. Run the search command to check the
+           value of passwordSendExpiringTime attribute
+    :expectedresults:
+        1. Valid values should be accepted and saved
+        2. Should be rejected with an OPERATIONS_ERROR
+        3. The attribute should be changed for valid values
+           and unchanged for invalid
     """
 
     log.info('Get the default value')
@@ -280,19 +283,21 @@ def test_expiry_time(topology_st, global_policy, add_user):
     """Test whether the password expiry warning
     time for a user is returned appropriately
 
-    :ID: 7adfd395-9b25-4cc0-9b71-14710dc1a28c
-    :feature: Pasword Expiry Warning Time
-    :setup: Standalone DS instance with,
-            1. Global password policy configured as below:
-               passwordExp: on
-               passwordMaxAge: 172800
-               passwordWarning: 86400
-               passwordSendExpiringTime: on
-            2. User entry for binding
-    :steps: 1. Bind as the user
-            2. Request the control for the user
-    :expectedresults: The password expiry warning time for the user should be
-                      returned
+    :id: 7adfd395-9b25-4cc0-9b71-14710dc1a28c
+    :setup: Standalone instance, a user entry,
+            Global password policy configured as below:
+                passwordExp: on
+                passwordMaxAge: 172800
+                passwordWarning: 86400
+                passwordSendExpiringTime: on
+    :steps:
+        1. Bind as the normal user
+        2. Request password policy control for the user
+        3. Bind as DM
+    :expectedresults:
+        1. Bind should be successful
+        2. The password expiry warning time for the user should be returned
+        3. Bind should be successful
     """
 
     res_ctrls = None
@@ -315,27 +320,28 @@ def test_expiry_time(topology_st, global_policy, add_user):
 @pytest.mark.parametrize("attr,val", [(CONFIG_ATTR, 'off'),
                                       ('passwordWarning', '3600')])
 def test_password_warning(topology_st, global_policy, add_user, attr, val):
-    """Test password expiry warning time by
-    setting passwordSendExpiringTime to off
+    """Test password expiry warning time by setting passwordSendExpiringTime to off
     and setting passwordWarning to a short value
 
-    :ID: 39f54b3c-8c80-43ca-856a-174d81c56ce8
-    :feature: Password Expiry Warning Time
-    :setup: Standalone DS instance with,
-           1. Global password policy configures as below:
-              passwordExp: on
-              passwordMaxAge: 172800
-              passwordWarning: 86400
-              passwordSendExpiringTime: on
-           2. User entry for binding
-    :steps: 1a. Set passwordSendExpiringTime attribute to off.
-            1b. In the another attempt, try to set passwordWarning
-               to a small value (for eg: 3600 seconds)
-            2. Bind as the user
-            3a. Request the control for the user
-            3b. Request the password expiry warning time
-    :expectedresults: a. Password expiry warning time should not be returned
-                      b. Password expiry warning time should be returned
+    :id: 39f54b3c-8c80-43ca-856a-174d81c56ce8
+    :setup: Standalone instance, a test user,
+            Global password policy configured as below:
+                passwordExp: on
+                passwordMaxAge: 172800
+                passwordWarning: 86400
+                passwordSendExpiringTime: on
+    :steps:
+        1. Set passwordSendExpiringTime attribute to off or
+           to on and passwordWarning to a small value (3600)
+        2. Bind as the normal user
+        3. Request the password expiry warning time
+        4. Bind as DM
+    :expectedresults:
+        1. passwordSendExpiringTime and passwordWarning are set successfully
+        2. Bind should be successful
+        3. Password expiry warning time should be returned for the small value
+           and should not be returned when passwordSendExpiringTime is off
+        4. Bind should be successful
     """
 
     try:
@@ -361,32 +367,33 @@ def test_password_warning(topology_st, global_policy, add_user, attr, val):
 def test_with_different_password_states(topology_st, global_policy, add_user):
     """Test the control with different password states
 
-    :ID: d297fb1a-661f-4d52-bb43-2a2a340b8b0e
-    :feature: Password Expiry Warning Time
-    :setup: Standalone DS instance with,
-            1. Global password policy configured as below:
-               passwordExp: on
-               passwordMaxAge: 172800
-               passwordWarning: 86400
-               passwordSendExpiringTime: on
-            2. User entry for binding to the server
-    :steps: 1. Expire user's password by setting the system
-               date past the valid period for the password
-            2. Try to bind to the server with the user entry
-            3. Set the system date to the current day
-            4. Try to bind with the user entry and request
-               the control
+    :id: d297fb1a-661f-4d52-bb43-2a2a340b8b0e
+    :setup: Standalone instance, a user entry,
+            Global password policy configured as below:
+                passwordExp: on
+                passwordMaxAge: 172800
+                passwordWarning: 86400
+                passwordSendExpiringTime: on
+    :steps:
+        1. Expire user's password by changing
+           passwordExpirationTime timestamp
+        2. Try to bind to the server with the user entry
+        3. Revert back user's passwordExpirationTime
+        4. Try to bind with the user entry and request
+           the control
+        5. Bind as DM
     :expectedresults:
-            1. In the first try, the bind should fail with an
-            INVALID_CREDENTIALS error
-            2. In the second try, the bind should be successful
-            and the password expiry warning time should be
-            returned
+        1. Operation should be successful
+        2. Operation should fail because of Invalid Credentials
+        3. passwordExpirationTime is successfully changed
+        4. Bind should be successful and the password expiry
+           warning time should be returned
+        5. Bind should be successful
     """
 
     res_ctrls = None
 
-    log.info("Expiring user's password by changing" \
+    log.info("Expire user's password by changing" \
              "passwordExpirationTime timestamp")
     old_ts = topology_st.standalone.search_s(USER_DN, ldap.SCOPE_SUBTREE,
              '(objectClass=*)', ['passwordExpirationTime'])[0].getValue('passwordExpirationTime')
@@ -426,23 +433,23 @@ def test_with_different_password_states(topology_st, global_policy, add_user):
 
 
 def test_default_behavior(topology_st, global_policy_default, add_user):
-    """Test the default behavior of password
-    expiry warning time
-
-    :ID: c47fa824-ee08-4b78-885f-bca4c42bb655
-    :feature: Password Expiry Warning Time
-    :setup: Standalone DS instance with,
-            1. Global password policy configured as follows,
-               passwordExp: on
-               passwordMaxAge: 8640000
-               passwordWarning: 86400
-               passwordSendExpiringTime: off
-            2. User entry for binding to the server
-    :steps: 1. Bind as the user
-            2. Request the control for the user
+    """Test the default behavior of password expiry warning time
+
+    :id: c47fa824-ee08-4b78-885f-bca4c42bb655
+    :setup: Standalone instance, a user entry,
+            Global password policy configured as below:
+                passwordExp: on
+                passwordMaxAge: 8640000
+                passwordWarning: 86400
+                passwordSendExpiringTime: off
+    :steps:
+        1. Bind as the normal user
+        2. Request the control for the user
+        3. Bind as DM
     :expectedresults:
-            1. Bind should be successful
-            2. No control should be returned
+        1. Bind should be successful
+        2. No control should be returned
+        3. Bind should be successful
     """
 
     res_ctrls = None
@@ -464,23 +471,24 @@ def test_when_maxage_and_warning_are_the_same(topology_st, global_policy_default
     passwordWarning are set to the same value.
 
     :id: e57a1b1c-96fc-11e7-a91b-28d244694824
-    :feature: Password Expiry Warning Time
-    :setup: Standalone DS instance with,
-            1. Global password policy configured as follows,
-               passwordExp: on
-               passwordMaxAge: 86400
-               passwordWarning: 86400
-               passwordSendExpiringTime: off
-            2. User entry for binding to the server
-    :steps: 1. Bind as the user
-            2. Change user's password to reset its password expiration time
-            3. Request the control for the user
+    :setup: Standalone instance, a user entry,
+            Global password policy configured as below:
+                passwordExp: on
+                passwordMaxAge: 86400
+                passwordWarning: 86400
+                passwordSendExpiringTime: off
+    :steps:
+        1. Bind as the normal user
+        2. Change user's password to reset its password expiration time
+        3. Request the control for the user
+        4. Bind as DM
     :expectedresults:
-            1. Bind should be successful
-            2. Password should be changed and password's expiration time reset
-            3. Password expiry warning time should be returned by the
-            server since passwordMaxAge and passwordWarning are set
-            to the same value
+        1. Bind should be successful
+        2. Password should be changed and password's expiration time reset
+        3. Password expiry warning time should be returned by the
+           server since passwordMaxAge and passwordWarning are set
+           to the same value
+        4. Bind should be successful
     """
 
     log.info('Set the new values')
@@ -509,26 +517,24 @@ def test_when_maxage_and_warning_are_the_same(topology_st, global_policy_default
 
 
 def test_with_local_policy(topology_st, global_policy, local_policy):
-    """Test the attribute with fine grained policy
-    set for the user
-
-    :ID: ab7d9f86-8cfe-48c3-8baa-739e599f006a
-    :feature: Password Expiry Warning Time
-    :setup: Standalone DS instance with,
-            1. Global password policy configured as below,
-               passwordExp: on
-               passwordMaxAge: 172800
-               passwordWarning: 86400
-               passwordSendExpiringTime: on
-            2. User entry for binding to the server
-            3. Configure fine grained password policy for the user
-               as below:
-               ns-newpwpolicy.pl -D 'cn=Directory Manager' -w secret123
-               -h localhost -p 389 -U 'uid=tuser,dc=example,dc=com'
-    :steps: 1. Bind as the user
-            2. Request the control for the user
-    :expectedresults: Password expiry warning time should not be returned for the
-                      user
+    """Test the attribute with fine grained policy set for the user
+
+    :id: ab7d9f86-8cfe-48c3-8baa-739e599f006a
+    :setup: Standalone instance, a user entry,
+            Global password policy configured as below:
+                passwordExp: on
+                passwordMaxAge: 172800
+                passwordWarning: 86400
+                passwordSendExpiringTime: on
+            Fine grained password policy for the user using ns-newpwpolicy.pl
+    :steps:
+        1. Bind as the normal user
+        2. Request the control for the user
+        3. Bind as DM
+    :expectedresults:
+        1. Bind should be successful
+        2. Password expiry warning time should not be returned for the user
+        3. Bind should be successful
     """
 
     res_ctrls = None
diff --git a/dirsrvtests/tests/suites/password/pwd_lockout_bypass_test.py b/dirsrvtests/tests/suites/password/pwd_lockout_bypass_test.py
index e4add728e..1a0aef1ed 100644
--- a/dirsrvtests/tests/suites/password/pwd_lockout_bypass_test.py
+++ b/dirsrvtests/tests/suites/password/pwd_lockout_bypass_test.py
@@ -20,7 +20,32 @@ BAD_PASSWORD = 'aontseunao'
 logging.getLogger(__name__).setLevel(logging.INFO)
 log = logging.getLogger(__name__)
 
+
 def test_lockout_bypass(topology_st):
+    """Check basic password lockout functionality
+
+    :id: 2482a992-1719-495c-b75b-78fe5c48c873
+    :setup: Standalone instance
+    :steps:
+        1. Set passwordMaxFailure to 1
+        2. Set passwordLockDuration to 7
+        3. Set passwordLockout to 'on'
+        4. Create a user
+        5. Set a userPassword attribute
+        6. Bind as the user with a bad credentials
+        7. Bind as the user with a bad credentials
+        8. Bind as the user with a good credentials
+    :expectedresults:
+        1. passwordMaxFailure should be successfully set
+        2. passwordLockDuration should be successfully set
+        3. passwordLockout should be successfully set
+        4. User should be created
+        5. userPassword should be successfully set
+        6. Should throw an invalid credentials error
+        7. Should throw a constraint violation error
+        8. Should throw a constraint violation error
+    """
+
     inst = topology_st.standalone
 
     # Configure the lock policy
diff --git a/dirsrvtests/tests/suites/password/pwp_history_test.py b/dirsrvtests/tests/suites/password/pwp_history_test.py
index 1ec1fa06b..f391646f3 100644
--- a/dirsrvtests/tests/suites/password/pwp_history_test.py
+++ b/dirsrvtests/tests/suites/password/pwp_history_test.py
@@ -17,12 +17,36 @@ logging.getLogger(__name__).setLevel(logging.DEBUG)
 log = logging.getLogger(__name__)
 
 
-def test_pwp_history_test(topology_st):
-    """
-    Test password policy history feature:
-        - Test password history is enforced
-        - Test password history works after an Admin resets the password
-        - Test that the correct number of passwords are stored in history
+def test_basic(topology_st):
+    """Test basic password policy history feature functionality
+
+    :id: 83d74f7d-3036-4944-8839-1b40bbf265ff
+    :setup: Standalone instance
+    :steps:
+        1. Configure password history policy as bellow:
+             passwordHistory: on
+             passwordInHistory: 3
+             passwordChange: on
+             passwordStorageScheme: CLEAR
+        2. Add a test user
+        3. Attempt to change password to the same password
+        4. Change password four times
+        5. Check that we only have 3 passwords stored in history
+        6. Attempt to change the password to previous passwords
+        7. Reset password by Directory Manager (admin reset)
+        8. Try and change the password to the previous password before the reset
+    :expectedresults:
+        1. Password history policy should be configured successfully
+        2. User should be added successfully
+        3. Password change should be correctly rejected
+           with Constrant Violation error
+        4. Password should be successfully changed
+        5. Only 3 passwords should be stored in history
+        6. Password changes should be correctly rejected
+           with Constrant Violation error
+        7. Password should be successfully reset
+        8. Password change should be correctly rejected
+           with Constrant Violation error
     """
 
     USER_DN = 'uid=testuser,' + DEFAULT_SUFFIX
@@ -139,7 +163,7 @@ def test_pwp_history_test(topology_st):
     time.sleep(1)
 
     #
-    # Check that we only have 3 passwords stored in history\
+    # Check that we only have 3 passwords stored in history
     #
     try:
         entry = topology_st.standalone.search_s(USER_DN, ldap.SCOPE_BASE,
diff --git a/dirsrvtests/tests/suites/password/regression_test.py b/dirsrvtests/tests/suites/password/regression_test.py
index f6ee16773..409a4f0f3 100644
--- a/dirsrvtests/tests/suites/password/regression_test.py
+++ b/dirsrvtests/tests/suites/password/regression_test.py
@@ -82,17 +82,17 @@ def test_trivial_passw_check(topo, passw_policy, test_user, user_pasw):
     """PasswordCheckSyntax attribute fails to validate cn, sn, uid, givenname, ou and mail attributes
 
     :id: bf9fe1ef-56cb-46a3-a6f8-5530398a06dc
-    :feature: Password policy
     :setup: Standalone instance.
-    :steps: 1. Configure local password policy with PasswordCheckSyntax set to on.
-            2. Add users with cn, sn, uid, givenname, mail and userPassword attributes.
-            3. Configure subtree password policy for ou=people subtree.
-            4. Reset userPassword with trivial values like cn, sn, uid, givenname, ou and mail attributes.
+    :steps:
+        1. Configure local password policy with PasswordCheckSyntax set to on.
+        2. Add users with cn, sn, uid, givenname, mail and userPassword attributes.
+        3. Configure subtree password policy for ou=people subtree.
+        4. Reset userPassword with trivial values like cn, sn, uid, givenname, ou and mail attributes.
     :expectedresults:
-            1. Enabling PasswordCheckSyntax should PASS.
-            2. Add users should PASS.
-            3. Configure subtree password policy should PASS.
-            4. Resetting userPassword to cn, sn, uid and mail should be rejected.
+        1. Enabling PasswordCheckSyntax should PASS.
+        2. Add users should PASS.
+        3. Configure subtree password policy should PASS.
+        4. Resetting userPassword to cn, sn, uid and mail should be rejected.
     """
 
     conn = test_user.bind(PASSWORD)
@@ -112,15 +112,15 @@ def test_global_vs_local(topo, passw_policy, test_user, user_pasw):
     """Passwords rejected if its similar to uid, cn, sn, givenname, ou and mail attributes
 
     :id: dfd6cf5d-8bcd-4895-a691-a43ad9ec1be8
-    :feature: Password policy
     :setup: Standalone instance
-    :steps: 1. Configure global password policy with PasswordCheckSyntax set to off
-            2. Add users with cn, sn, uid, mail, givenname and userPassword attributes
-            3. Replace userPassword similar to cn, sn, uid, givenname, ou and mail attributes
+    :steps:
+        1. Configure global password policy with PasswordCheckSyntax set to off
+        2. Add users with cn, sn, uid, mail, givenname and userPassword attributes
+        3. Replace userPassword similar to cn, sn, uid, givenname, ou and mail attributes
     :expectedresults:
-            1. Disabling the local policy should PASS.
-            2. Add users should PASS.
-            3. Resetting userPasswords similar to cn, sn, uid, givenname, ou and mail attributes should PASS.
+        1. Disabling the local policy should PASS.
+        2. Add users should PASS.
+        3. Resetting userPasswords similar to cn, sn, uid, givenname, ou and mail attributes should PASS.
     """
 
     log.info('Configure Pwpolicy with PasswordCheckSyntax and nsslapd-pwpolicy-local set to off')
diff --git a/dirsrvtests/tests/suites/replication/__init__.py b/dirsrvtests/tests/suites/replication/__init__.py
index e69de29bb..c5117a9f1 100644
--- a/dirsrvtests/tests/suites/replication/__init__.py
+++ b/dirsrvtests/tests/suites/replication/__init__.py
@@ -0,0 +1,18 @@
+import time
+import ldap
+from lib389._constants import DEFAULT_SUFFIX
+
+
+def get_repl_entries(topo, entry_name, attr_list):
+    """Get a list of test entries from all masters"""
+
+    entries_list = []
+
+    time.sleep(10)
+
+    for inst in topo.all_insts.values():
+        entries = inst.search_s(DEFAULT_SUFFIX, ldap.SCOPE_SUBTREE, "uid={}".format(entry_name), attr_list)
+        entries_list += entries
+
+    return entries_list
+
diff --git a/dirsrvtests/tests/suites/replication/acceptance_test.py b/dirsrvtests/tests/suites/replication/acceptance_test.py
index 2897726f5..d7c1dfc1c 100644
--- a/dirsrvtests/tests/suites/replication/acceptance_test.py
+++ b/dirsrvtests/tests/suites/replication/acceptance_test.py
@@ -10,12 +10,8 @@ import pytest
 from lib389.tasks import *
 from lib389.utils import *
 from lib389.topologies import topology_m4 as topo_m4
-
-from lib389._constants import (BACKEND_NAME, DEFAULT_SUFFIX, LOG_REPLICA, REPLICA_RUV_FILTER,
-                              ReplicaRole, REPLICATION_BIND_DN, REPLICATION_BIND_PW,
-                              REPLICATION_BIND_METHOD, REPLICATION_TRANSPORT, defaultProperties,
-                              RA_NAME, RA_BINDDN, RA_BINDPW, RA_METHOD, RA_TRANSPORT_PROT,
-                              DN_DM, PASSWORD, LOG_DEFAULT, RA_ENABLED, RA_SCHEDULE)
+from lib389._constants import *
+from . import get_repl_entries
 
 TEST_ENTRY_NAME = 'mmrepl_test'
 TEST_ENTRY_DN = 'uid={},{}'.format(TEST_ENTRY_NAME, DEFAULT_SUFFIX)
@@ -90,33 +86,15 @@ def new_suffix(topo_m4, request):
     request.addfinalizer(fin)
 
 
-def get_repl_entries(topo, entry_name, attr_list):
-    """Get a list of test entries from all masters"""
-
-    entries_list = []
-    num_of_masters = len({name: inst for name, inst in topo.ms.items() if not name.endswith('agmts')})
-
-    log.info('Wait for replication to happen')
-    time.sleep(10)
-
-    for num in range(1, num_of_masters + 1):
-        entries = topo.ms['master{}'.format(num)].search_s(DEFAULT_SUFFIX, ldap.SCOPE_SUBTREE,
-                                                           "uid={}".format(entry_name), attr_list)
-        entries_list += entries
-
-    return entries_list
-
-
 def test_add_entry(topo_m4, test_entry):
     """Check that entries are replicated after add operation
 
-    :ID: 024250f1-5f7e-4f3b-a9f5-27741e6fd405
-    :feature: Multi master replication
-    :setup: Four masters replication setup
-    :steps: 1. Add entry to master1
-            2. Wait for replication to happen
-            3. Check entry on all other masters
-    :expectedresults: Entry should be replicated
+    :id: 024250f1-5f7e-4f3b-a9f5-27741e6fd405
+    :setup: Four masters replication setup, an entry
+    :steps:
+        1. Check entry on all other masters
+    :expectedresults:
+        1. The entry should be replicated to all masters
     """
 
     entries = get_repl_entries(topo_m4, TEST_ENTRY_NAME, ["uid"])
@@ -126,13 +104,28 @@ def test_add_entry(topo_m4, test_entry):
 def test_modify_entry(topo_m4, test_entry):
     """Check that entries are replicated after modify operation
 
-    :ID: 36764053-622c-43c2-a132-d7a3ab7d9aaa
-    :feature: Multi master replication
+    :id: 36764053-622c-43c2-a132-d7a3ab7d9aaa
     :setup: Four masters replication setup, an entry
-    :steps: 1. Modify the entry on master1 (try add, modify and delete operations)
-            2. Wait for replication to happen
-            3. Check entry on all other masters
-    :expectedresults: Entry attr should be replicated
+    :steps:
+        1. Modify the entry on master1 - add attribute
+        2. Wait for replication to happen
+        3. Check entry on all other masters
+        4. Modify the entry on master1 - replace attribute
+        5. Wait for replication to happen
+        6. Check entry on all other masters
+        7. Modify the entry on master1 - delete attribute
+        8. Wait for replication to happen
+        9. Check entry on all other masters
+    :expectedresults:
+        1. Attribute should be successfully added
+        2. Some time should pass
+        3. The change should be present on all masters
+        4. Attribute should be successfully replaced
+        5. Some time should pass
+        6. The change should be present on all masters
+        4. Attribute should be successfully deleted
+        8. Some time should pass
+        9. The change should be present on all masters
     """
 
     log.info('Modifying entry {} - add operation'.format(TEST_ENTRY_DN))
@@ -181,13 +174,14 @@ def test_modify_entry(topo_m4, test_entry):
 def test_delete_entry(topo_m4, test_entry):
     """Check that entry deletion is replicated after delete operation
 
-    :ID: 18437262-9d6a-4b98-a47a-6182501ab9bc
-    :feature: Multi master replication
+    :id: 18437262-9d6a-4b98-a47a-6182501ab9bc
     :setup: Four masters replication setup, an entry
-    :steps: 1. Delete the entry from master1
-            2. Wait for replication to happen
-            3. Check entry on all other masters
-    :expectedresults: Entry deletion should be replicated
+    :steps:
+        1. Delete the entry from master1
+        2. Check entry on all other masters
+    :expectedresults:
+        1. The entry should be deleted
+        2. The change should be present on all masters
     """
 
     log.info('Deleting entry {} during the test'.format(TEST_ENTRY_DN))
@@ -201,14 +195,14 @@ def test_delete_entry(topo_m4, test_entry):
 def test_modrdn_entry(topo_m4, test_entry, delold):
     """Check that entries are replicated after modrdn operation
 
-    :ID: 02558e6d-a745-45ae-8d88-34fe9b16adc9
-    :feature: Multi master replication
+    :id: 02558e6d-a745-45ae-8d88-34fe9b16adc9
     :setup: Four masters replication setup, an entry
-    :steps: 1. Make modrdn operation on entry on master1 with both delold 1 and 0
-            2. Wait for replication to happen
-            3. Check entry on all other masters
-    :expectedresults: Entry with new RDN should be replicated.
-                     If delold was specified, entry with old RDN shouldn't exist
+    :steps:
+        1. Make modrdn operation on entry on master1 with both delold 1 and 0
+        2. Check entry on all other masters
+    :expectedresults:
+        1. Modrdn operation should be successful
+        2. The change should be present on all masters
     """
 
     newrdn_name = 'newrdn'
@@ -239,15 +233,20 @@ def test_modrdn_entry(topo_m4, test_entry, delold):
 def test_modrdn_after_pause(topo_m4):
     """Check that changes are properly replicated after replica pause
 
-    :ID: 6271dc9c-a993-4a9e-9c6d-05650cdab282
-    :feature: Multi master replication
+    :id: 6271dc9c-a993-4a9e-9c6d-05650cdab282
     :setup: Four masters replication setup, an entry
-    :steps: 1. Pause all replicas
-            2. Make modrdn operation on entry on master1
-            3. Resume all replicas
-            4. Wait for replication to happen
-            5. Check entry on all other masters
-    :expectedresults: Entry with new RDN should be replicated.
+    :steps:
+        1. Pause all replicas
+        2. Make modrdn operation on entry on master1
+        3. Resume all replicas
+        4. Wait for replication to happen
+        5. Check entry on all other masters
+    :expectedresults:
+        1. Replicas should be paused
+        2. Modrdn operation should be successful
+        3. Replicas should be resumed
+        4. Some time should pass
+        5. The change should be present on all masters
     """
 
     newrdn_name = 'newrdn'
@@ -293,16 +292,18 @@ def test_modrdn_after_pause(topo_m4):
         topo_m4.ms["master1"].delete_s(newrdn_dn)
 
 
-# Bugzilla 842441
+@pytest.mark.bz842441
 def test_modify_stripattrs(topo_m4):
     """Check that we can modify nsds5replicastripattrs
 
-    :ID: f36abed8-e262-4f35-98aa-71ae55611aaa
-    :feature: Multi master replication
+    :id: f36abed8-e262-4f35-98aa-71ae55611aaa
     :setup: Four masters replication setup
-    :steps: 1. Modify nsds5replicastripattrs attribute on any agreement
-            2. Search for the modified attribute
+    :steps:
+        1. Modify nsds5replicastripattrs attribute on any agreement
+        2. Search for the modified attribute
     :expectedresults: It should be contain the value
+        1. nsds5replicastripattrs should be successfully set
+        2. The modified attribute should be the one we set
     """
 
     m1 = topo_m4.ms["master1"]
@@ -320,13 +321,16 @@ def test_modify_stripattrs(topo_m4):
 def test_new_suffix(topo_m4, new_suffix):
     """Check that we can enable replication on a new suffix
 
-    :ID: d44a9ed4-26b0-4189-b0d0-b2b336ddccbd
-    :feature: Multi master replication
-    :setup: Four masters replication setup, new suffix
-    :steps: 1. Enable replication on the new suffix
-            2. Check if it works
-            3. Disable replication on the new suffix
-    :expectedresults: Replication works on the new suffix
+    :id: d44a9ed4-26b0-4189-b0d0-b2b336ddccbd
+    :setup: Four masters replication setup, a new suffix
+    :steps:
+        1. Enable replication on the new suffix
+        2. Check if replication works
+        3. Disable replication on the new suffix
+    :expectedresults:
+        1. Replication on the new suffix should be enabled
+        2. Replication should work
+        3. Replication on the new suffix should be disabled
     """
 
     m1 = topo_m4.ms["master1"]
@@ -369,14 +373,17 @@ def test_new_suffix(topo_m4, new_suffix):
 def test_many_attrs(topo_m4, test_entry):
     """Check a replication with many attributes (add and delete)
 
-    :ID: d540b358-f67a-43c6-8df5-7c74b3cb7523
-    :feature: Multi master replication
+    :id: d540b358-f67a-43c6-8df5-7c74b3cb7523
     :setup: Four masters replication setup, a test entry
-    :steps: 1. Add 10 new attributes to the entry
-            2. Delete one from the beginning, two from the middle
-               and one from the end
-            3. Check that the changes were replicated in the right order
-    :expectedresults: All changes are successfully replicated in the right order
+    :steps:
+        1. Add 10 new attributes to the entry
+        2. Delete few attributes: one from the beginning,
+           two from the middle and one from the end
+        3. Check that the changes were replicated in the right order
+    :expectedresults:
+        1. The attributes should be successfully added
+        2. Delete operations should be successful
+        3. The changes should be replicated in the right order
     """
 
     m1 = topo_m4.ms["master1"]
@@ -412,118 +419,6 @@ def test_many_attrs(topo_m4, test_entry):
             assert value not in delete_list
 
 
-def test_double_delete(topo_m4, test_entry):
-    """Check that double delete of the entry doesn't crash server
-
-    :ID: 3496c82d-636a-48c9-973c-2455b12164cc
-    :feature: Multi master replication
-    :setup: Four masters replication setup, a test entry
-    :steps: 1. Delete the entry
-            2. Delete the entry on the second master
-            3. Check that server is alive
-    :expectedresults: Server hasn't crash
-    """
-
-    log.info('Deleting entry {} from master1'.format(TEST_ENTRY_DN))
-    topo_m4.ms["master1"].delete_s(TEST_ENTRY_DN)
-
-    log.info('Deleting entry {} from master2'.format(TEST_ENTRY_DN))
-    try:
-        topo_m4.ms["master2"].delete_s(TEST_ENTRY_DN)
-    except ldap.NO_SUCH_OBJECT:
-        log.info("Entry {} wasn't found master2. It is expected.".format(TEST_ENTRY_DN))
-
-    log.info('Make searches to check if server is alive')
-    entries = get_repl_entries(topo_m4, TEST_ENTRY_NAME, ["uid"])
-    assert not entries, "Entry deletion {} wasn't replicated successfully".format(TEST_ENTRY_DN)
-
-
-def test_password_repl_error(topo_m4, test_entry):
-    """Check that error about userpassword replication is properly logged
-
-    :ID: 714130ff-e4f0-4633-9def-c1f4b24abfef
-    :feature: Multi master replication
-    :setup: Four masters replication setup, a test entry
-    :steps: 1. Change userpassword on master 1
-            2. Restart the servers to flush the logs
-            3. Check the error log for an replication error
-    :expectedresults: We don't have a replication error in the error log
-    """
-
-    m1 = topo_m4.ms["master1"]
-    m2 = topo_m4.ms["master2"]
-    TEST_ENTRY_NEW_PASS = 'new_{}'.format(TEST_ENTRY_NAME)
-
-    log.info('Clean the error log')
-    m2.deleteErrorLogs()
-
-    log.info('Set replication loglevel')
-    m2.setLogLevel(LOG_REPLICA)
-
-    log.info('Modifying entry {} - change userpassword on master 2'.format(TEST_ENTRY_DN))
-    try:
-        m1.modify_s(TEST_ENTRY_DN, [(ldap.MOD_REPLACE, 'userpassword', 'new_{}'.format(TEST_ENTRY_NAME))])
-    except ldap.LDAPError as e:
-        log.error('Failed to modify entry (%s): error (%s)' % (TEST_ENTRY_DN,
-                                                               e.message['desc']))
-        raise e
-
-    log.info('Restart the servers to flush the logs')
-    for num in range(1, 5):
-        topo_m4.ms["master{}".format(num)].restart(timeout=10)
-
-    try:
-        log.info('Check that password works on master 2')
-        m2.simple_bind_s(TEST_ENTRY_DN, TEST_ENTRY_NEW_PASS)
-        m2.simple_bind_s(DN_DM, PASSWORD)
-
-        log.info('Check the error log for the error with {}'.format(TEST_ENTRY_DN))
-        assert not m2.ds_error_log.match('.*can.t add a change for uid={}.*'.format(TEST_ENTRY_NAME))
-    finally:
-        log.info('Reset bind DN to Directory manager')
-        for num in range(1, 5):
-            topo_m4.ms["master{}".format(num)].simple_bind_s(DN_DM, PASSWORD)
-        log.info('Set the default loglevel')
-        m2.setLogLevel(LOG_DEFAULT)
-
-
-def test_invalid_agmt(topo_m4):
-    """Test adding that an invalid agreement is properly rejected and does not crash the server
-
-    :id: 6c3b2a7e-edcd-4327-a003-6bd878ff722b
-    :setup: MMR with four masters
-    :steps:
-        1. Add invalid agreement (nsds5ReplicaEnabled set to invalid value)
-        2. Verify the server is still running
-    :expectedresults:
-        1. Invalid repl agreement should be rejected
-        2. Server should be still running
-    """
-    m1 = topo_m4.ms["master1"]
-
-    # Add invalid agreement (nsds5ReplicaEnabled set to invalid value)
-    AGMT_DN = 'cn=whatever,cn=replica,cn="dc=example,dc=com",cn=mapping tree,cn=config'
-    try:
-        invalid_props = {RA_ENABLED: 'True',  # Invalid value
-                         RA_SCHEDULE: '0001-2359 0123456'}
-        m1.agreement.create(suffix=DEFAULT_SUFFIX, host='localhost', port=389, properties=invalid_props)
-    except ldap.UNWILLING_TO_PERFORM:
-        m1.log.info('Invalid repl agreement correctly rejected')
-    except ldap.LDAPError as e:
-        m1.log.fatal('Got unexpected error adding invalid agreement: ' + str(e))
-        assert False
-    else:
-        m1.log.fatal('Invalid agreement was incorrectly accepted by the server')
-        assert False
-
-    # Verify the server is still running
-    try:
-        m1.simple_bind_s(DN_DM, PASSWORD)
-    except ldap.LDAPError as e:
-        m1.log.fatal('Failed to bind: ' + str(e))
-        assert False
-
-
 if __name__ == '__main__':
     # Run isolated
     # -s for DEBUG mode
diff --git a/dirsrvtests/tests/suites/replication/cleanallruv_test.py b/dirsrvtests/tests/suites/replication/cleanallruv_test.py
index 620a53e1a..a042fbdd6 100644
--- a/dirsrvtests/tests/suites/replication/cleanallruv_test.py
+++ b/dirsrvtests/tests/suites/replication/cleanallruv_test.py
@@ -9,18 +9,11 @@
 import threading
 
 import pytest
+from lib389 import DirSrv
 from lib389.tasks import *
 from lib389.utils import *
 from lib389.topologies import topology_m4
-
-from lib389._constants import (DEFAULT_SUFFIX, REPLICA_RUV_FILTER, ReplicaRole,
-                              REPLICAID_MASTER_4, REPLICAID_MASTER_3, REPLICAID_MASTER_2,
-                              REPLICAID_MASTER_1, REPLICATION_BIND_DN, REPLICATION_BIND_PW,
-                              REPLICATION_BIND_METHOD, REPLICATION_TRANSPORT, SUFFIX,
-                              RA_NAME, RA_BINDDN, RA_BINDPW, RA_METHOD, RA_TRANSPORT_PROT,
-                              defaultProperties, args_instance)
-
-from lib389 import DirSrv
+from lib389._constants import *
 
 logging.getLogger(__name__).setLevel(logging.DEBUG)
 log = logging.getLogger(__name__)
@@ -224,15 +217,20 @@ def restore_master4(topology_m4):
 def test_clean(topology_m4):
     """Check that cleanallruv task works properly
 
-    :ID: e9b3ce5c-e17c-409e-aafc-e97d630f2878
-    :feature: CleanAllRUV
+    :id: e9b3ce5c-e17c-409e-aafc-e97d630f2878
     :setup: Replication setup with four masters
-    :steps: 1. Check that replication works on all masters
-            2. Disable replication on master 4
-            3. Remove agreements to master 4 from other masters
-            4. Run a cleanallruv task on master 1 with a 'force' option 'on'
-            5. Check that everything was cleaned and no hanging tasks left
-    :expectedresults: Everything was cleaned and no hanging tasks left
+    :steps:
+        1. Check that replication works on all masters
+        2. Disable replication on master 4
+        3. Remove agreements to master 4 from other masters
+        4. Run a cleanallruv task on master 1 with a 'force' option 'on'
+        5. Check that everything was cleaned
+    :expectedresults:
+        1. Replication should work properly on all masters
+        2. Operation should be successful
+        3. Agreements to master 4 should be removed
+        4. Cleanallruv task should be successfully executed
+        5. Everything should be cleaned
     """
 
     log.info('Running test_clean...')
@@ -285,18 +283,30 @@ def test_clean(topology_m4):
 def test_clean_restart(topology_m4):
     """Check that cleanallruv task works properly after a restart
 
-    :ID: c6233bb3-092c-4919-9ac9-80dd02cc6e02
-    :feature: CleanAllRUV
+    :id: c6233bb3-092c-4919-9ac9-80dd02cc6e02
     :setup: Replication setup with four masters
-    :steps: 1. Disable replication on master 4
-            2. Remove agreements to master 4 from other masters
-            3. Stop master 3
-            4. Run a cleanallruv task on master 1
-            5. Stop master 1
-            6. Start master 3 and make sure that no crash happened
-            7. Start master 1 and make sure that no crash happened
-            8. Check that everything was cleaned and no hanging tasks left
-    :expectedresults: Everything was cleaned and no hanging tasks left
+    :steps:
+        1. Disable replication on master 4
+        2. Remove agreements to master 4 from other masters
+        3. Stop master 3
+        4. Run a cleanallruv task on master 1
+        5. Stop master 1
+        6. Start master 3
+        7. Make sure that no crash happened
+        8. Start master 1
+        9. Make sure that no crash happened
+        10. Check that everything was cleaned
+    :expectedresults:
+        1. Operation should be successful
+        2. Agreements to master 4 should be removed
+        3. Master 3 should be stopped
+        4. Cleanallruv task should be successfully executed
+        5. Master 1 should be stopped
+        6. Master 3 should be started
+        7. No crash should happened
+        8. Master 1 should be started
+        9. No crash should happened
+        10. Everything should be cleaned
     """
 
     log.info('Running test_clean_restart...')
@@ -358,17 +368,24 @@ def test_clean_restart(topology_m4):
 def test_clean_force(topology_m4):
     """Check that multiple tasks with a 'force' option work properly
 
-    :ID: eb76a93d-8d1c-405e-9f25-6e8d5a781098
-    :feature: CleanAllRUV
+    :id: eb76a93d-8d1c-405e-9f25-6e8d5a781098
     :setup: Replication setup with four masters
-    :steps: 1. Stop master 3
-            2. Add a bunch of updates to master 4
-            3. Disable replication on master 4
-            4. Start master 3
-            5. Remove agreements to master 4 from other masters
-            6. Run a cleanallruv task on master 1 with a 'force' option 'on'
-            7. Check that everything was cleaned and no hanging tasks left
-    :expectedresults: Everything was cleaned and no hanging tasks left
+    :steps:
+        1. Stop master 3
+        2. Add a bunch of updates to master 4
+        3. Disable replication on master 4
+        4. Start master 3
+        5. Remove agreements to master 4 from other masters
+        6. Run a cleanallruv task on master 1 with a 'force' option 'on'
+        7. Check that everything was cleaned
+    :expectedresults:
+        1. Master 3 should be stopped
+        2. Operation should be successful
+        3. Replication on master 4 should be disabled
+        4. Master 3 should be started
+        5. Agreements to master 4 should be removed
+        6. Operation should be successful
+        7. Everything should be cleaned
     """
 
     log.info('Running test_clean_force...')
@@ -418,17 +435,20 @@ def test_clean_force(topology_m4):
 def test_abort(topology_m4):
     """Test the abort task basic functionality
 
-    :ID: b09a6887-8de0-4fac-8e41-73ccbaaf7a08
-    :feature: CleanAllRUV
+    :id: b09a6887-8de0-4fac-8e41-73ccbaaf7a08
     :setup: Replication setup with four masters
-    :steps: 1. Disable replication on master 4
-            2. Remove agreements to master 4 from other masters
-            3. Stop master 2
-            4. Run a cleanallruv task on master 1
-            5. Run a cleanallruv abort task on master 1
-            6. Wait for the task to be done
-            7. Check that no hanging tasks left
+    :steps:
+        1. Disable replication on master 4
+        2. Remove agreements to master 4 from other masters
+        3. Stop master 2
+        4. Run a cleanallruv task on master 1
+        5. Run a cleanallruv abort task on master 1
     :expectedresults: No hanging tasks left
+        1. Replication on master 4 should be disabled
+        2. Agreements to master 4 should be removed
+        3. Master 2 should be stopped
+        4. Operation should be successful
+        5. Operation should be successful
     """
 
     log.info('Running test_abort...')
@@ -497,20 +517,30 @@ def test_abort(topology_m4):
 def test_abort_restart(topology_m4):
     """Test the abort task can handle a restart, and then resume
 
-    :ID: b66e33d4-fe85-4e1c-b882-75da80f70ab3
-    :feature: CleanAllRUV
+    :id: b66e33d4-fe85-4e1c-b882-75da80f70ab3
     :setup: Replication setup with four masters
-    :steps: 1. Disable replication on master 4
-            2. Remove agreements to master 4 from other masters
-            3. Stop master 3
-            4. Run a cleanallruv task on master 1
-            5. Run a cleanallruv abort task on master 1
-            6. Restart master 1 and make sure that no crash happened
-            7. Start master 3
-            8. Check that abort task was resumed on master 1
-               and errors log doesn't have 'Aborting abort task' message
-    :expectedresults: Abort task was resumed on master 1
-                      and errors log doesn't have 'Aborting abort task' message
+    :steps:
+        1. Disable replication on master 4
+        2. Remove agreements to master 4 from other masters
+        3. Stop master 3
+        4. Run a cleanallruv task on master 1
+        5. Run a cleanallruv abort task on master 1
+        6. Restart master 1
+        7. Make sure that no crash happened
+        8. Start master 3
+        9. Check master 1 does not have the clean task running
+        10. Check that errors log doesn't have 'Aborting abort task' message
+    :expectedresults:
+        1. Replication on master 4 should be disabled
+        2. Agreements to master 4 should be removed
+        3. Master 3 should be stopped
+        4. Operation should be successful
+        5. Operation should be successful
+        6. Master 1 should be restarted
+        7. No crash should happened
+        8. Master 3 should be started
+        9. Check master 1 shouldn't have the clean task running
+        10. Errors log shouldn't have 'Aborting abort task' message
     """
 
     log.info('Running test_abort_restart...')
@@ -593,17 +623,20 @@ def test_abort_restart(topology_m4):
 def test_abort_certify(topology_m4):
     """Test the abort task with a replica-certify-all option
 
-    :ID: 78959966-d644-44a8-b98c-1fcf21b45eb0
-    :feature: CleanAllRUV
+    :id: 78959966-d644-44a8-b98c-1fcf21b45eb0
     :setup: Replication setup with four masters
-    :steps: 1. Disable replication on master 4
-            2. Remove agreements to master 4 from other masters
-            3. Stop master 2
-            4. Run a cleanallruv task on master 1
-            5. Run a cleanallruv abort task on master 1 with a replica-certify-all option
-            6. Wait for the task to be done
-            7. Check that no hanging tasks left
+    :steps:
+        1. Disable replication on master 4
+        2. Remove agreements to master 4 from other masters
+        3. Stop master 2
+        4. Run a cleanallruv task on master 1
+        5. Run a cleanallruv abort task on master 1 with a replica-certify-all option
     :expectedresults: No hanging tasks left
+        1. Replication on master 4 should be disabled
+        2. Agreements to master 4 should be removed
+        3. Master 2 should be stopped
+        4. Operation should be successful
+        5. Operation should be successful
     """
 
     log.info('Running test_abort_certify...')
@@ -689,17 +722,23 @@ def test_abort_certify(topology_m4):
 def test_stress_clean(topology_m4):
     """Put each server(m1 - m4) under a stress, and perform the entire clean process
 
-    :ID: a8263cd6-f068-4357-86e0-e7c34504c8c5
-    :feature: CleanAllRUV
+    :id: a8263cd6-f068-4357-86e0-e7c34504c8c5
     :setup: Replication setup with four masters
-    :steps: 1. Add a bunch of updates to all masters
-            2. Put master 4 to read-only mode
-            3. Disable replication on master 4 and wait for the changes
-            4. Start master 3
-            5. Remove agreements to master 4 from other masters
-            6. Run a cleanallruv task on master 1
-            7. Check that everything was cleaned and no hanging tasks left
-    :expectedresults: Everything was cleaned and no hanging tasks left
+    :steps:
+        1. Add a bunch of updates to all masters
+        2. Put master 4 to read-only mode
+        3. Disable replication on master 4
+        5. Remove agreements to master 4 from other masters
+        6. Run a cleanallruv task on master 1
+        7. Check that everything was cleaned
+    :expectedresults:
+        1. Operation should be successful
+        2. Master 4 should be put to read-only mode
+        3. Replication on master 4 should be disabled
+        2. Agreements to master 4 should be removed
+        5. Agreements to master 4 should be removed
+        6. Operation should be successful
+        7. Everything should be cleaned
     """
 
     log.info('Running test_stress_clean...')
@@ -788,18 +827,26 @@ def test_stress_clean(topology_m4):
 def test_multiple_tasks_with_force(topology_m4):
     """Check that multiple tasks with a 'force' option work properly
 
-    :ID: eb76a93d-8d1c-405e-9f25-6e8d5a781098
-    :feature: CleanAllRUV
+    :id: eb76a93d-8d1c-405e-9f25-6e8d5a781098
     :setup: Replication setup with four masters
-    :steps: 1. Stop master 3
-            2. Add a bunch of updates to master 4
-            3. Disable replication on master 4
-            4. Start master 3
-            5. Remove agreements to master 4 from other masters
-            6. Run a cleanallruv task on master 1 with a 'force' option 'on'
-            7. Run one more cleanallruv task on master 1 with a 'force' option 'off'
-            8. Check that everything was cleaned and no hanging tasks left
-    :expectedresults: Everything was cleaned and no hanging tasks left
+    :steps:
+        1. Stop master 3
+        2. Add a bunch of updates to master 4
+        3. Disable replication on master 4
+        4. Start master 3
+        5. Remove agreements to master 4 from other masters
+        6. Run a cleanallruv task on master 1 with a 'force' option 'on'
+        7. Run one more cleanallruv task on master 1 with a 'force' option 'off'
+        8. Check that everything was cleaned
+    :expectedresults:
+        1. Master 3 should be stopped
+        2. Operation should be successful
+        3. Replication on master 4 should be disabled
+        4. Master 3 should be started
+        5. Agreements to master 4 should be removed
+        6. Operation should be successful
+        7. Operation should be successful
+        8. Everything should be cleaned
     """
 
     log.info('Running test_multiple_tasks_with_force...')
diff --git a/dirsrvtests/tests/suites/replication/regression_test.py b/dirsrvtests/tests/suites/replication/regression_test.py
new file mode 100644
index 000000000..e72d15c61
--- /dev/null
+++ b/dirsrvtests/tests/suites/replication/regression_test.py
@@ -0,0 +1,172 @@
+# --- BEGIN COPYRIGHT BLOCK ---
+# Copyright (C) 2017 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.idm.user import TEST_USER_PROPERTIES, UserAccounts
+from lib389.utils import *
+from lib389.topologies import topology_m2 as topo_m2
+from lib389._constants import *
+from . import get_repl_entries
+
+NEW_SUFFIX_NAME = 'test_repl'
+NEW_SUFFIX = 'o={}'.format(NEW_SUFFIX_NAME)
+NEW_BACKEND = 'repl_base'
+
+DEBUGGING = os.getenv("DEBUGGING", default=False)
+if DEBUGGING:
+    logging.getLogger(__name__).setLevel(logging.DEBUG)
+else:
+    logging.getLogger(__name__).setLevel(logging.INFO)
+log = logging.getLogger(__name__)
+
+
+@pytest.fixture(scope="function")
+def test_entry(topo_m2, request):
+    """Add test entry using UserAccounts"""
+
+    log.info('Adding a test entry user')
+    users = UserAccounts(topo_m2.ms["master1"], DEFAULT_SUFFIX)
+    tuser = users.create(properties=TEST_USER_PROPERTIES)
+
+    def fin():
+        if users.list():
+            log.info('Deleting user-{}'.format(tuser.dn))
+            tuser.delete()
+        else:
+            log.info('There is no user to delete')
+
+    request.addfinalizer(fin)
+    return tuser
+
+
+def test_double_delete(topo_m2, test_entry):
+    """Check that double delete of the entry doesn't crash server
+
+    :id: 3496c82d-636a-48c9-973c-2455b12164cc
+    :setup: Four masters replication setup, a test entry
+    :steps:
+        1. Delete the entry on the first master
+        2. Delete the entry on the second master
+        3. Check that server is alive
+    :expectedresults:
+        1. Entry should be successfully deleted from first master
+        2. Entry should be successfully deleted from second aster
+        3. Server should me alive
+    """
+
+    test_entry_rdn = test_entry.rdn
+
+    log.info('Deleting entry {} from master1'.format(test_entry.dn))
+    topo_m2.ms["master1"].delete_s(test_entry.dn)
+
+    log.info('Deleting entry {} from master2'.format(test_entry.dn))
+    try:
+        topo_m2.ms["master2"].delete_s(test_entry.dn)
+    except ldap.NO_SUCH_OBJECT:
+        log.info("Entry {} wasn't found master2. It is expected.".format(test_entry.dn))
+
+    log.info('Make searches to check if server is alive')
+    entries = get_repl_entries(topo_m2, test_entry_rdn, ["uid"])
+    assert not entries, "Entry deletion {} wasn't replicated successfully".format(test_entry.dn)
+
+
+def test_password_repl_error(topo_m2, test_entry):
+    """Check that error about userpassword replication is properly logged
+
+    :id: 714130ff-e4f0-4633-9def-c1f4b24abfef
+    :setup: Four masters replication setup, a test entry
+    :steps:
+        1. Change userpassword on the first master
+        2. Restart the servers to flush the logs
+        3. Check the error log for an replication error
+    :expectedresults:
+        1. Password should be successfully changed
+        2. Server should be successfully restarted
+        3. There should be no replication errors in the error log
+    """
+
+    m1 = topo_m2.ms["master1"]
+    m2 = topo_m2.ms["master2"]
+    TEST_ENTRY_NEW_PASS = 'new_pass'
+
+    log.info('Clean the error log')
+    m2.deleteErrorLogs()
+
+    log.info('Set replication loglevel')
+    m2.setLogLevel(LOG_REPLICA)
+
+    log.info('Modifying entry {} - change userpassword on master 2'.format(test_entry.dn))
+    try:
+        m1.modify_s(test_entry.dn, [(ldap.MOD_REPLACE, 'userpassword', TEST_ENTRY_NEW_PASS)])
+    except ldap.LDAPError as e:
+        log.error('Failed to modify entry (%s): error (%s)' % (test_entry.dn,
+                                                               e.message['desc']))
+        raise e
+
+    log.info('Restart the servers to flush the logs')
+    for num in range(1, 3):
+        topo_m2.ms["master{}".format(num)].restart(timeout=10)
+
+    try:
+        log.info('Check that password works on master 2')
+        m2.simple_bind_s(test_entry.dn, TEST_ENTRY_NEW_PASS)
+        m2.simple_bind_s(DN_DM, PASSWORD)
+
+        log.info('Check the error log for the error with {}'.format(test_entry.dn))
+        assert not m2.ds_error_log.match('.*can.t add a change for {}.*'.format(test_entry.dn))
+    finally:
+        log.info('Reset bind DN to Directory manager')
+        for num in range(1, 3):
+            topo_m2.ms["master{}".format(num)].simple_bind_s(DN_DM, PASSWORD)
+        log.info('Set the default loglevel')
+        m2.setLogLevel(LOG_DEFAULT)
+
+
+def test_invalid_agmt(topo_m2):
+    """Test adding that an invalid agreement is properly rejected and does not crash the server
+
+    :id: 6c3b2a7e-edcd-4327-a003-6bd878ff722b
+    :setup: Four masters replication setup
+    :steps:
+        1. Add invalid agreement (nsds5ReplicaEnabled set to invalid value)
+        2. Verify the server is still running
+    :expectedresults:
+        1. Invalid repl agreement should be rejected
+        2. Server should be still running
+    """
+
+    m1 = topo_m2.ms["master1"]
+
+    # Add invalid agreement (nsds5ReplicaEnabled set to invalid value)
+    AGMT_DN = 'cn=whatever,cn=replica,cn="dc=example,dc=com",cn=mapping tree,cn=config'
+    try:
+        invalid_props = {RA_ENABLED: 'True',  # Invalid value
+                         RA_SCHEDULE: '0001-2359 0123456'}
+        m1.agreement.create(suffix=DEFAULT_SUFFIX, host='localhost', port=389, properties=invalid_props)
+    except ldap.UNWILLING_TO_PERFORM:
+        m1.log.info('Invalid repl agreement correctly rejected')
+    except ldap.LDAPError as e:
+        m1.log.fatal('Got unexpected error adding invalid agreement: ' + str(e))
+        assert False
+    else:
+        m1.log.fatal('Invalid agreement was incorrectly accepted by the server')
+        assert False
+
+    # Verify the server is still running
+    try:
+        m1.simple_bind_s(DN_DM, PASSWORD)
+    except ldap.LDAPError as e:
+        m1.log.fatal('Failed to bind: ' + str(e))
+        assert False
+
+
+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/single_master_test.py b/dirsrvtests/tests/suites/replication/single_master_test.py
index 95ad1f55b..44cd5cf53 100644
--- a/dirsrvtests/tests/suites/replication/single_master_test.py
+++ b/dirsrvtests/tests/suites/replication/single_master_test.py
@@ -81,17 +81,23 @@ def replica_without_init(topo_nr):
 def test_mail_attr_repl(topo_r, test_user):
     """Check that no crash happens during mail attribute replication
 
-    :ID: 959edc84-05be-4bf9-a541-53afae482052
-    :feature: Single master replication
+    :id: 959edc84-05be-4bf9-a541-53afae482052
     :setup: Replication setup with master and consumer instances,
             test user on master
-    :steps: 1. Check that user was replicated to consumer
-            2. Back up mail database file
-            3. Remove mail attribute from the user entry
-            4. Restore mail database
-            5. Search for the entry with a substring 'mail=user*'
-            6. Search for the entry once again to make sure that server is alive
-    :expectedresults: No crash happens
+    :steps:
+        1. Check that user was replicated to consumer
+        2. Back up mail database file
+        3. Remove mail attribute from the user entry
+        4. Restore mail database
+        5. Search for the entry with a substring 'mail=user*'
+        6. Search for the entry once again to make sure that server is alive
+    :expectedresults:
+        1. The user should be replicated to consumer
+        2. Operation should be successful
+        3. The mail attribute should be removed
+        4. Operation should be successful
+        5. Search should be successful
+        6. No crash should happen
     """
 
     master = topo_r.ms["master1"]
@@ -144,15 +150,18 @@ def test_mail_attr_repl(topo_r, test_user):
 def test_lastupdate_attr_before_init(topo_nr, replica_without_init):
     """Check that LastUpdate replica attributes show right values
 
-    :ID: bc8ce431-ff65-41f5-9331-605cbcaaa887
-    :feature: Single master replication
+    :id: bc8ce431-ff65-41f5-9331-605cbcaaa887
     :setup: Replication setup with master and consumer instances
             without initialization
-    :steps: 1. Check nsds5replicaLastUpdateStart, nsds5replicaLastUpdateEnd,
-               nsds5replicaLastUpdateStatus attrs
-    :expectedresults: nsds5replicaLastUpdateStart: 0, nsds5replicaLastUpdateEnd: 0 and
-             nsds5replicaLastUpdateStatus is not equal to
-             "0 Replica acquired successfully: Incremental update started"
+    :steps:
+        1. Check nsds5replicaLastUpdateStart value
+        2. Check nsds5replicaLastUpdateEnd value
+        3. Check nsds5replicaLastUpdateStatus value
+    :expectedresults:
+        1. nsds5replicaLastUpdateStart should be equal to 0
+        2. nsds5replicaLastUpdateEnd should be equal to 0
+        3. nsds5replicaLastUpdateStatus should not be equal
+           to "0 Replica acquired successfully: Incremental update started"
     """
 
     master = topo_nr.ins["standalone1"]
diff --git a/dirsrvtests/tests/suites/replication/tombstone_test.py b/dirsrvtests/tests/suites/replication/tombstone_test.py
index d1a817832..a70114809 100644
--- a/dirsrvtests/tests/suites/replication/tombstone_test.py
+++ b/dirsrvtests/tests/suites/replication/tombstone_test.py
@@ -13,17 +13,22 @@ from lib389.topologies import topology_st
 
 from lib389._constants import DEFAULT_SUFFIX, ReplicaRole, REPLICAID_MASTER_1
 
+
 def test_purge_success(topology_st):
     """Verify that tombstones are created successfully
 
-    :ID: adb86f50-ae76-4ed6-82b4-3cdc30ccab78
-    :feature: nsTombstone
+    :id: adb86f50-ae76-4ed6-82b4-3cdc30ccab78
     :setup: Standalone instance
-    :steps: 1. Enable replication to unexisting instance
-            2. Add an entry to the replicated suffix
-            3. Delete the entry
-            4. Check that tombstone entry exists (objectclass=nsTombstone)
+    :steps:
+        1. Enable replication to unexisting instance
+        2. Add an entry to the replicated suffix
+        3. Delete the entry
+        4. Check that tombstone entry exists (objectclass=nsTombstone)
     :expectedresults: Tombstone entry exist
+        1. Operation should be successful
+        2. The entry should be successfully added
+        3. The entry should be successfully deleted
+        4. Tombstone entry should exist
     """
 
     log.info('Setting up replication...')
diff --git a/dirsrvtests/tests/suites/replication/wait_for_async_feature_test.py b/dirsrvtests/tests/suites/replication/wait_for_async_feature_test.py
index cac25f80f..21edbeee7 100644
--- a/dirsrvtests/tests/suites/replication/wait_for_async_feature_test.py
+++ b/dirsrvtests/tests/suites/replication/wait_for_async_feature_test.py
@@ -96,7 +96,18 @@ def entries(topology_m2, request):
 
 
 def test_not_int_value(topology_m2):
-    """Tests not integer value"""
+    """Tests not integer value
+
+    :id: 67c9994f-9251-425a-8197-8d12ad9beafc
+    :setup: Replication with two masters
+    :steps:
+        1. Try to set some string value
+           to nsDS5ReplicaWaitForAsyncResults
+    :expectedresults:
+        1. Invalid syntax error should be raised
+    """
+
+
     master1 = topology_m2.ms["master1"]
     agmt = master1.agreement.list(suffix=DEFAULT_SUFFIX)[0].dn
 
@@ -109,7 +120,19 @@ def test_not_int_value(topology_m2):
 
 
 def test_multi_value(topology_m2):
-    """Tests multi value"""
+    """Tests multi value
+
+    :id: 1932301a-db29-407e-b27e-4466a876d1d3
+    :setup: Replication with two masters
+    :steps:
+        1. Set nsDS5ReplicaWaitForAsyncResults to some int
+        2. Try to add one more int value
+           to nsDS5ReplicaWaitForAsyncResults
+    :expectedresults:
+        1. nsDS5ReplicaWaitForAsyncResults should be set
+        2. Object class violation error should be raised
+    """
+
     master1 = topology_m2.ms["master1"]
     agmt = master1.agreement.list(suffix=DEFAULT_SUFFIX)[0].dn
 
@@ -127,7 +150,19 @@ def test_multi_value(topology_m2):
 
 
 def test_value_check(topology_m2, waitfor_async_attr):
-    """Checks that value has been set correctly"""
+    """Checks that value has been set correctly
+
+    :id: 3e81afe9-5130-410d-a1bb-d798d8ab8519
+    :setup: Replication with two masters,
+        wait for async set on all masters, try:
+        None, '2000', '0', '-5'
+    :steps:
+        1. Search for nsDS5ReplicaWaitForAsyncResults on master 1
+        2. Search for nsDS5ReplicaWaitForAsyncResults on master 2
+    :expectedresults:
+        1. nsDS5ReplicaWaitForAsyncResults should be set correctly
+        2. nsDS5ReplicaWaitForAsyncResults should be set correctly
+    """
 
     attr_value = waitfor_async_attr[0]
 
@@ -152,6 +187,22 @@ def test_value_check(topology_m2, waitfor_async_attr):
 def test_behavior_with_value(topology_m2, waitfor_async_attr, entries):
     """Tests replication behavior with valid
     nsDS5ReplicaWaitForAsyncResults attribute values
+
+    :id: 117b6be2-cdab-422e-b0c7-3b88bbeec036
+    :setup: Replication with two masters,
+        wait for async set on all masters, try:
+        None, '2000', '0', '-5'
+    :steps:
+        1. Set Replication Debugging loglevel for the errorlog
+        2. Set nsslapd-logging-hr-timestamps-enabled to 'off' on both masters
+        3. Gather all sync attempts,  group by timestamp
+        4. Take the most common timestamp and assert it has appeared
+           in the set range
+    :expectedresults:
+        1. Replication Debugging loglevel should be set
+        2. nsslapd-logging-hr-timestamps-enabled  should be set
+        3. Operation should be successful
+        4. Errors log should have all timestamp appear
     """
 
     master1 = topology_m2.ms["master1"]
diff --git a/dirsrvtests/tests/suites/sasl/allowed_mechs.py b/dirsrvtests/tests/suites/sasl/allowed_mechs_test.py
similarity index 64%
rename from dirsrvtests/tests/suites/sasl/allowed_mechs.py
rename to dirsrvtests/tests/suites/sasl/allowed_mechs_test.py
index 5b1b92ce1..81b1c047c 100644
--- a/dirsrvtests/tests/suites/sasl/allowed_mechs.py
+++ b/dirsrvtests/tests/suites/sasl/allowed_mechs_test.py
@@ -12,30 +12,64 @@ import os
 from lib389.topologies import topology_st
 
 
-def test_sasl_allowed_mechs(topology_st):
+def test_basic_feature(topology_st):
     """Test the alloweed sasl mechanism feature
 
-    :ID: ab7d9f86-8cfe-48c3-8baa-739e599f006a
-    :feature: Allowed sasl mechanisms
-    :steps: 1.  Get the default list of mechanisms
-            2.  Set allowed mechanism PLAIN, and verify it's correctly listed
-            3.  Restart server, and verify list is still correct
-            4.  Test EXTERNAL is properly listed
-            5.  Add GSSAPI to the existing list, and verify it's correctly listed
-            6.  Restart server and verify list is still correct
-            7.  Add ANONYMOUS to the existing list, and veirfy it's correctly listed
-            8.  Restart server and verify list is still correct
-            9.  Remove GSSAPI and verify it's correctly listed
-            10. Restart server and verify list is still correct
-            11. Reset allowed list to nothing, verify "all" the mechanisms are returned
-            12. Restart server and verify list is still correct
-
-    :expectedresults: The supported mechanisms supported what is set for the allowed
-                      mechanisms
+    :id: ab7d9f86-8cfe-48c3-8baa-739e599f006a
+    :setup: Standalone instance
+    :steps:
+        1. Get the default list of mechanisms
+        2. Set allowed mechanism PLAIN
+        3. Verify the list
+        4. Restart the server
+        5. Verify that list is still correct
+        6. Edit mechanisms to allow just PLAIN and EXTERNAL
+        7. Verify the list
+        8. Edit mechanisms to allow just PLAIN and GSSAPI
+        9. Verify the list
+        10. Restart the server
+        11. Verify that list is still correct
+        12. Edit mechanisms to allow just PLAIN, GSSAPI, and ANONYMOUS
+        13. Verify the list
+        14. Restart the server
+        15. Verify that list is still correct
+        16. Edit mechanisms to allow just PLAIN and ANONYMOUS
+        17. Verify the list
+        18. Restart the server
+        19. Verify that list is still correct
+        20. Reset the allowed list to nothing,
+        21. Verify that the returned mechanisms are the default ones
+        22. Restart the server
+        23. Verify that list is still correct
+    :expectedresults:
+        1. GSSAPI, PLAIN and EXTERNAL mechanisms should be acquired
+        2. Operation should be successful
+        3. List should have - PLAIN, EXTERNAL; shouldn't have - GSSAPI
+        4. Server should be restarted
+        5. List should have - PLAIN, EXTERNAL; shouldn't have - GSSAPI
+        6. Operation should be successful
+        7. List should have - PLAIN, EXTERNAL; shouldn't have - GSSAPI
+        8. Operation should be successful
+        9. List should have - PLAIN, EXTERNAL, GSSAPI
+        10. Server should be restarted
+        11. List should have - PLAIN, EXTERNAL, GSSAPI
+        12. Operation should be successful
+        13. List should have - PLAIN, EXTERNAL, GSSAPI, ANONYMOUS
+        14. Server should be restarted
+        15. List should have - PLAIN, EXTERNAL, GSSAPI, ANONYMOUS
+        16. Operation should be successful
+        17. List should have - PLAIN, EXTERNAL, ANONYMOUS; shouldn't have - GSSAPI
+        18. Server should be restarted
+        19. List should have - PLAIN, EXTERNAL, ANONYMOUS; shouldn't have - GSSAPI
+        20. Operation should be successful
+        21. List should have - PLAIN, EXTERNAL, GSSAPI
+        22. Server should be restarted
+        23. List should have - PLAIN, EXTERNAL, GSSAPI
     """
+
     standalone = topology_st.standalone
 
-    # Get the supported mechs. This should contain PLAIN, GSSAPI, EXTERNAL at least
+    # Get the supported mechanisms. This should contain PLAIN, GSSAPI, EXTERNAL at least
     standalone.log.info("Test we have some of the default mechanisms")
     orig_mechs = standalone.rootdse.supported_sasl()
     print(orig_mechs)
@@ -43,7 +77,7 @@ def test_sasl_allowed_mechs(topology_st):
     assert('PLAIN' in orig_mechs)
     assert('EXTERNAL' in orig_mechs)
 
-    # Now edit the supported mechs. Check them again.
+    # Now edit the supported mechanisms. Check them again.
     standalone.log.info("Edit mechanisms to allow just PLAIN")
     standalone.config.set('nsslapd-allowed-sasl-mechanisms', 'PLAIN')
     limit_mechs = standalone.rootdse.supported_sasl()
@@ -68,7 +102,7 @@ def test_sasl_allowed_mechs(topology_st):
     assert('EXTERNAL' in limit_mechs)
     assert('GSSAPI' not in limit_mechs)
 
-    # Now edit the supported mechs. Check them again.
+    # Now edit the supported mechanisms. Check them again.
     standalone.log.info("Edit mechanisms to allow just PLAIN and GSSAPI")
     standalone.config.set('nsslapd-allowed-sasl-mechanisms', 'PLAIN, GSSAPI')
     limit_mechs = standalone.rootdse.supported_sasl()
@@ -86,7 +120,7 @@ def test_sasl_allowed_mechs(topology_st):
     assert('GSSAPI' in limit_mechs)
     assert(len(limit_mechs) == 3)
 
-    # Add ANONYMOUS to the supported mechs and test again.
+    # Add ANONYMOUS to the supported mechanisms and test again.
     standalone.log.info("Edit mechanisms to allow just PLAIN, GSSAPI, and ANONYMOUS")
     standalone.config.set('nsslapd-allowed-sasl-mechanisms', 'PLAIN, GSSAPI, ANONYMOUS')
     limit_mechs = standalone.rootdse.supported_sasl()
diff --git a/dirsrvtests/tests/suites/sasl/plain.py b/dirsrvtests/tests/suites/sasl/plain_test.py
similarity index 99%
rename from dirsrvtests/tests/suites/sasl/plain.py
rename to dirsrvtests/tests/suites/sasl/plain_test.py
index a48e34081..cff250707 100644
--- a/dirsrvtests/tests/suites/sasl/plain.py
+++ b/dirsrvtests/tests/suites/sasl/plain_test.py
@@ -20,7 +20,7 @@ from lib389.idm.services import ServiceAccounts
 log = logging.getLogger(__name__)
 
 
-def test_sasl_plain(topology_st):
+def test_basic_feature(topology_st):
     """Check basic SASL functionality for PLAIN mechanism
 
     :id: 75ddc6fa-aa5a-4025-9c71-1abad20c91fc
-- 
2.13.6

