From 5878a3113c0a28ff8fc3a23452afd8895ffed06c Mon Sep 17 00:00:00 2001 From: Anuj Borah Date: Feb 12 2020 09:19:00 +0000 Subject: Issue: 50686 - Port fractional replication test cases from TET to python3 part 1 Bug Description: Port fractional replication test cases from TET to python3 part 1 Relates: https://pagure.io/389-ds-base/issue/50686 Author: aborah Reviewed by: Viktor Ashirov --- diff --git a/dirsrvtests/tests/suites/fractional/fractional_test.py b/dirsrvtests/tests/suites/fractional/fractional_test.py new file mode 100644 index 0000000..32dee16 --- /dev/null +++ b/dirsrvtests/tests/suites/fractional/fractional_test.py @@ -0,0 +1,267 @@ +# --- BEGIN COPYRIGHT BLOCK --- +# Copyright (C) 2020 Red Hat, Inc. +# All rights reserved. +# +# License: GPL (version 3 or any later version). +# See LICENSE for details. +# --- END COPYRIGHT BLOCK --- +# +""" +This test script will test fractional replication. +""" + +import os +import pytest +from lib389.topologies import topology_m2c2 +from lib389._constants import DEFAULT_SUFFIX +from lib389.idm.user import UserAccounts, UserAccount +from lib389.replica import ReplicationManager +from lib389.agreement import Agreements +import ldap + +pytestmark = pytest.mark.tier1 + +MASTER1 = MASTER2 = CONSUMER1 = CONSUMER2 = None + + +def _create_users(instance, cn_cn, sn_sn, givenname, ou_ou, l_l, uid, mail, + telephonenumber, facsimiletelephonenumber, roomnumber): + """ + Will create sample user. + """ + user = instance.create(properties={ + 'cn': cn_cn, + 'sn': sn_sn, + 'givenname': givenname, + 'ou': ou_ou, + 'l': l_l, + 'uid': uid, + 'mail': mail, + 'telephonenumber': telephonenumber, + 'facsimiletelephonenumber': facsimiletelephonenumber, + 'roomnumber': roomnumber, + 'uidNumber': '111', + 'gidNumber': '111', + 'homeDirectory': f'/home/{uid}', + + }) + return user + + +def check_all_replicated(): + """ + Will check replication status + """ + for master in [MASTER2, CONSUMER1, CONSUMER2]: + ReplicationManager(DEFAULT_SUFFIX).wait_for_replication(MASTER1, master, timeout=100) + + +@pytest.fixture(scope="module") +def _create_entries(topology_m2c2): + """ + A fixture that will create first test user and create fractional Agreement + """ + # Defining as global , as same value will be used everywhere with same name. + global MASTER1, MASTER2, CONSUMER1, CONSUMER2 + MASTER1 = topology_m2c2.ms['master1'] + MASTER2 = topology_m2c2.ms['master2'] + CONSUMER1 = topology_m2c2.cs['consumer1'] + CONSUMER2 = topology_m2c2.cs['consumer2'] + users = UserAccounts(MASTER1, DEFAULT_SUFFIX) + _create_users(users, 'Sam Carter', 'Carter', 'Sam', ['Accounting', 'People'], + 'Sunnyvale', 'scarter', 'scarter@red.com', '+1 408 555 4798', + '+1 408 555 9751', '4612') + for ins, num in [(MASTER1, 1), (MASTER2, 2), (MASTER1, 2), (MASTER2, 1)]: + Agreements(ins).list()[num].replace( + 'nsDS5ReplicatedAttributeList', + '(objectclass=*) $ EXCLUDE audio businessCategory carLicense departmentNumber ' + 'destinationIndicator displayName employeeNumber employeeType facsimileTelephoneNumber ' + 'roomNumber telephoneNumber memberOf manager accountUnlockTime ' + 'passwordRetryCount retryCountResetTime') + Agreements(ins).list()[num].replace( + 'nsDS5ReplicatedAttributeListTotal', + '(objectclass=*) $ EXCLUDE audio businessCategory carLicense departmentNumber ' + 'destinationIndicator displayName employeeNumber employeeType facsimileTelephoneNumber ' + 'roomNumber telephoneNumber accountUnlockTime passwordRetryCount retryCountResetTime') + Agreements(ins).list()[num].begin_reinit() + Agreements(ins).list()[num].wait_reinit() + + +def test_fractional_agreements(_create_entries): + """The attributes should be present on the two suppliers with traditional replication + agreements, but not with fractional agreements. + + :id: f22395e0-38ea-11ea-abe0-8c16451d917b + :setup: Master and Consumer + :steps: + 1. Add test entry + 2. Search for an entry with disallowed attributes on every server. + 3. The attributes should be present on the two suppliers with traditional replication + agreements + 4. Should be missing on both consumers with fractional agreements. + :expected results: + 1. Success + 2. Success + 3. Success + 4. Success + """ + check_all_replicated() + # Search for an entry with disallowed attributes on every server. + for attr in ['telephonenumber', 'facsimiletelephonenumber', 'roomnumber']: + assert UserAccount(MASTER1, f'uid=scarter,ou=People,{DEFAULT_SUFFIX}').get_attr_val(attr) + assert UserAccount(MASTER2, f'uid=scarter,ou=People,{DEFAULT_SUFFIX}').get_attr_val(attr) + # The attributes should be present on the two suppliers with + # traditional replication agreements + for attr in ['telephonenumber', 'facsimiletelephonenumber', 'roomnumber']: + assert not UserAccount(CONSUMER1, + f'uid=scarter,ou=People,{DEFAULT_SUFFIX}').get_attr_val(attr) + assert not UserAccount(CONSUMER2, + f'uid=scarter,ou=People,{DEFAULT_SUFFIX}').get_attr_val(attr) + + +def test_read_only_consumer(_create_entries): + """Attempt to modify an entry on read-only consumer. + + :id: f97f0fea-38ea-11ea-a617-8c16451d917b + :setup: Master and Consumer + :steps: + 1. Add test entry + 2. First attempt to modify an attribute that should be visible (mail) + 3. Then attempt to modify one that should not be visible (roomnumber) + :expected results: + 1. Success + 2. Fail(ldap.INSUFFICIENT_ACCESS) + 3. Fail(ldap.INSUFFICIENT_ACCESS) + """ + # Add test entry + user_consumer1 = UserAccount(CONSUMER1, f'uid=scarter,ou=People,{DEFAULT_SUFFIX}') + user_consumer2 = UserAccount(CONSUMER2, f'uid=scarter,ou=People,{DEFAULT_SUFFIX}') + # First attempt to modify an attribute that should be visible (mail) + for attr, value in [('mail', 'anuj@borah.com'), ('roomnumber', '123')]: + with pytest.raises(ldap.INSUFFICIENT_ACCESS): + user_consumer1.replace(attr, value) + # Then attempt to modify one that should not be visible (room number) + for attr, value in [('mail', 'anuj@borah.com'), ('roomnumber', '123')]: + with pytest.raises(ldap.INSUFFICIENT_ACCESS): + user_consumer2.replace(attr, value) + + +def test_read_write_supplier(_create_entries): + """Attempt to modify an entry on read-write supplier + + :id: ff50a8b6-38ea-11ea-870f-8c16451d917b + :setup: Master and Consumer + :steps: + 1. Add test entry + 2. First attempt to modify an attribute that should be visible (mail) + 3. Then attempt to modify one that should not be visible (roomnumber) + 4. The change to mail should appear on all servers; the change to + room number should only appear on the suppliers INST[0] and INST[1]. + :expected results: + 1. Success + 2. Success + 3. Success + 4. Success + """ + # Add test entry + user_master1 = UserAccount(MASTER1, f'uid=scarter,ou=People,{DEFAULT_SUFFIX}') + # First attempt to modify an attribute that should be visible (mail) + for attr, value in [('mail', 'anuj@borah.com'), ('roomnumber', '123')]: + user_master1.replace(attr, value) + check_all_replicated() + for ins, attr in [(MASTER2, 'mail'), + (MASTER2, 'roomnumber'), + (CONSUMER1, 'mail'), + (CONSUMER2, 'mail')]: + if attr == 'mail': + assert UserAccount(ins, + f'uid=scarter,' + f'ou=People,{DEFAULT_SUFFIX}').get_attr_val_utf8(attr) == \ + 'anuj@borah.com' + elif attr == 'roomnumber': + assert UserAccount(ins, + f'uid=scarter,' + f'ou=People,{DEFAULT_SUFFIX}').get_attr_val_utf8(attr) == '123' + # Attempt to modify one that should not be visible (room number) + for ins in [CONSUMER1, CONSUMER2]: + assert not UserAccount(ins, + f'uid=scarter,ou=People,{DEFAULT_SUFFIX}').get_attr_val('roomnumber') + + +def test_filtered_attributes(_create_entries): + """Filtered attributes are not replicated to CONSUMER1 or CONSUMER2. + + :id: 051b40ee-38eb-11ea-9126-8c16451d917b + :setup: Master and Consumer + :steps: + 1. Add a new entry to MASTER1. + 2. Confirm that it is replicated in entirety + to MASTER2, but that filtered attributes are not replicated to + CONSUMER1 or CONSUMER2. + 3. The entry should be present in all servers. Filtered attributes should not + be available from the consumers with fractional replication agreements. + :expected results: + 1. Success + 2. Success + 3. Success + """ + # Add a new entry to MASTER1. + users = UserAccounts(MASTER1, DEFAULT_SUFFIX) + _create_users(users, 'Anuj Borah', 'aborah', 'Anuj', 'People', 'ok', + 'aborah', 'aborah@aborah.com', '+1121', '+121', '2121') + check_all_replicated() + for instance in [MASTER1, MASTER2, CONSUMER1, CONSUMER2]: + assert UserAccount(instance, + f'uid=aborah,' + f'ou=People,{DEFAULT_SUFFIX}').get_attr_val_utf8('mail') == \ + 'aborah@aborah.com' + for instance in [MASTER1, MASTER2]: + assert UserAccount(instance, + f'uid=aborah,' + f'ou=People,{DEFAULT_SUFFIX}').get_attr_val_utf8('roomnumber') == '2121' + # The entry should be present in all servers. Filtered attributes should not + # be available from the consumers with fractional replication agreements. + for instance in [CONSUMER1, CONSUMER2]: + assert not UserAccount(instance, + f'uid=aborah,' + f'ou=People,{DEFAULT_SUFFIX}').get_attr_val_utf8('roomnumber') + + +@pytest.mark.bz154948 +def test_fewer_changes_in_single_operation(_create_entries): + """For bug 154948, which cause the server to crash if there were + fewer changes (but more than one) in a single operation to fractionally + replicated attributes than the number of fractionally replicated attributes. + The primary test is that all servers are still alive. + + :id: 0d1d6218-38eb-11ea-8945-8c16451d917b + :setup: Master and Consumer + :steps: + 1. Add a new entry to MASTER1. + 2. Fewer changes (but more than one) in a single operation to fractionally + replicated attributes than the number of fractionally replicated attributes. + 3. All servers are still alive. + :expected results: + 1. Success + 2. Success + 3. Success + """ + users = UserAccounts(MASTER1, DEFAULT_SUFFIX) + user = _create_users(users, 'Anuj Borah1', 'aborah1', 'Anuj1', 'People', + 'ok1', 'aborah1', 'aborah1@aborah1.com', '+11212', '+1212', '21231') + check_all_replicated() + # Fewer changes (but more than one) in a single operation to fractionally + # replicated attributes than the number of fractionally replicated attributes. + user.replace_many(('carLicense', '111-1111'), ('description', 'Hi')) + check_all_replicated() + user.replace_many(('mail', 'memail@ok.com'), ('sn', 'Oak'), ('l', 'NewPlace')) + check_all_replicated() + # All servers are still alive. + for ints in [MASTER1, MASTER2, CONSUMER1, CONSUMER2]: + assert UserAccount(ints, user.dn).get_attr_val_utf8('mail') == 'memail@ok.com' + assert UserAccount(ints, user.dn).get_attr_val_utf8('sn') == 'Oak' + + +if __name__ == '__main__': + CURRENT_FILE = os.path.realpath(__file__) + pytest.main("-s -v %s" % CURRENT_FILE)