From 2c49e4592cc093f182afbcd60391a5940f0932cf Mon Sep 17 00:00:00 2001 From: Simon Pichugin 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. 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 | 57 +++-- .../password/pwdPolicy_inherit_global_test.py | 65 ++--- .../tests/suites/password/pwdPolicy_syntax_test.py | 99 ++++++-- .../suites/password/pwdPolicy_warning_test.py | 226 +++++++++-------- .../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 ++++- dirsrvtests/tests/suites/sasl/allowed_mechs.py | 66 +++-- 19 files changed, 991 insertions(+), 564 deletions(-) create mode 100644 dirsrvtests/tests/suites/replication/regression_test.py 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..5454f9753 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 an user with userPassword attribute in cleartext + 2. Delete the userPassword attribute with the exact value + 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..127fd67b5 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 (who is no longer an admin) + 10. Make invalid password updates that should fail + 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, but this time they should succeed + 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, but they should succeed + 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 passwordAdminDN attributes + 2. Set passwordAdminDN attribute to an invalid value (ZZZZZ) + :expectedresults: + 1. Multiple passwordAdminDN attributes should be successfully added + 2. The operation should fail + """ + + # Add multiple attributes - one already exists so just try and add as 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..5081d35ed 100644 --- a/dirsrvtests/tests/suites/password/pwdPolicy_attribute_test.py +++ b/dirsrvtests/tests/suites/password/pwdPolicy_attribute_test.py @@ -127,19 +127,20 @@ 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 + :expectedresults: + 1. passwordChange should be successfully set + 2. Bind should be successful + 3. Subtree/User passwordChange - result + off/on, on/on - success + on/off, off/off - UNWILLING_TO_PERFORM """ log.info('Set passwordChange to "{}" - {}'.format(subtree_pwchange, @@ -196,21 +197,25 @@ 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 + :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 """ 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..f34b4f5ee 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: + a) 'off' and 'off' + b) 'on' and 'off' + c) 'off' and 'on' + 3. Try to add user with a short password + :expectedresults: + 1. Bind should be successful + 2. Attributes should be successfully set + 3. No exceptions should occur """ log.info('Set {} to {}'.format(ATTR_INHERIT_GLOBAL, inherit_value)) @@ -203,24 +201,29 @@ 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: + 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: + 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 """ 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..abcbeaa9e 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,80 @@ 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): + """Password policy test: 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 syntax check on + :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..11b9b0602 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 attr should be changed for valid values + and unchanged for invalid """ log.info('Get the default value') @@ -280,19 +283,19 @@ 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 with, a user entry, + Global password policy configured as below: + passwordExp: on + passwordMaxAge: 172800 + passwordWarning: 86400 + passwordSendExpiringTime: on + :steps: + 1. Bind as the user + 2. Request the control for the user + :expectedresults: + 1. Bind should be successful + 2. The password expiry warning time for the user should be returned """ res_ctrls = None @@ -315,27 +318,26 @@ 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 + 2. Bind as the user + 3. Request the password expiry warning time + :expectedresults: + 1. passwordSendExpiringTime and passwordWarning are set successfully + 2. Bind should be successful + 3. Password expiry warning time should be returned for a small value + and should not be returned when passwordSendExpiringTime is off """ try: @@ -361,27 +363,26 @@ 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 with, a user entry, + Global password policy configured as below: + passwordExp: on + passwordMaxAge: 172800 + passwordWarning: 86400 + passwordSendExpiringTime: on + :steps: + 1. Expiring 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 :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. passwordExpirationTime is successfully changed + 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 """ res_ctrls = None @@ -426,23 +427,21 @@ 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 with, a user entry, + Global password policy configured as below: + passwordExp: on + passwordMaxAge: 8640000 + passwordWarning: 86400 + passwordSendExpiringTime: off + :steps: + 1. Bind as the user + 2. Request the control for the user :expectedresults: - 1. Bind should be successful - 2. No control should be returned + 1. Bind should be successful + 2. No control should be returned """ res_ctrls = None @@ -464,23 +463,22 @@ 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 with, a user entry, + Global password policy configured as below: + passwordExp: on + passwordMaxAge: 86400 + passwordWarning: 86400 + passwordSendExpiringTime: off + :steps: + 1. Bind as the user + 2. Change user's password to reset its password expiration time + 3. Request the control for the user :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 """ log.info('Set the new values') @@ -509,26 +507,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 with, a user entry, + Global password policy configured as below: + passwordExp: on + passwordMaxAge: 172800 + passwordWarning: 86400 + passwordSendExpiringTime: on + 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: + 1. Bind should be successful + 2. Password expiry warning time should not be returned for the user """ 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..a03b5b560 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: + no value, '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: + no value, '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 within Counter dict, 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.py index 5b1b92ce1..13b8383b3 100644 --- a/dirsrvtests/tests/suites/sasl/allowed_mechs.py +++ b/dirsrvtests/tests/suites/sasl/allowed_mechs.py @@ -15,24 +15,56 @@ from lib389.topologies import topology_st def test_sasl_allowed_mechs(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 that PLAIN is correctly listed + 4. Restart the server + 5. Verify that list is still correct + 6. Verify that EXTERNAL is correctly listed + 7. Add GSSAPI to the existing list + 8. Verify that GSSAPI is correctly listed + 9. Restart the server + 10. Verify that list is still correct + 11. Add ANONYMOUS to the existing list + 12. Verify that ANONYMOUS is correctly listed + 13. Restart the server + 14. Verify that list is still correct + 15. Remove GSSAPI from the existing list + 16. Verify that GSSAPI is not in the list + 17. Restart the server + 18. Verify that list is still correct + 19. Reset the allowed list to nothing, + 20. Verify that the returned mechanisms are the default ones + 21. Restart the server + 22. Verify that list is still correct + :expectedresults: + 1. The list of mechanisms should be acquired + 2. Operation should be successful + 3. PLAIN should be correctly listed + 4. Server should be restarted + 5. List should be correct + 6. EXTERNAL should be correctly listed + 7. Operation should be successful + 8. GSSAPI should be correctly listed + 9. Server should be restarted + 10. List should be correct + 11. Operation should be successful + 12. ANONYMOUS should be correctly listed + 13. Server should be restarted + 14. List should be correct + 15. Operation should be successful + 16. GSSAPI should be correctly listed + 17. Server should be restarted + 18. List should be correct + 19. Operation should be successful + 20. The returned mechanisms should be the default ones + 21. Server should be restarted + 22. List should be correct """ + standalone = topology_st.standalone # Get the supported mechs. This should contain PLAIN, GSSAPI, EXTERNAL at least -- 2.13.6