From 4b53c3122bf2720941cf49c9be2a31808405399a Mon Sep 17 00:00:00 2001
From: Anuj Borah <aborah@redhat.com>
Date: Dec 18 2018 14:27:37 +0000
Subject:     Issue:  50082 - Port state test suite


    Description:  Port state test suite

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

    Reviewed by: Mark Reynolds

---

diff --git a/dirsrvtests/tests/suites/stat/__init__.py b/dirsrvtests/tests/suites/stat/__init__.py
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/dirsrvtests/tests/suites/stat/__init__.py
diff --git a/dirsrvtests/tests/suites/stat/mmt_state_test.py b/dirsrvtests/tests/suites/stat/mmt_state_test.py
new file mode 100644
index 0000000..2227389
--- /dev/null
+++ b/dirsrvtests/tests/suites/stat/mmt_state_test.py
@@ -0,0 +1,354 @@
+import os
+import logging
+import ldap
+import pytest
+from lib389.idm.user import UserAccounts
+from lib389.topologies import topology_m2 as topo
+from lib389._constants import *
+
+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__)
+
+BINVALUE1 = 'thedeadbeef1'
+BINVALUE2 = 'thedeadbeef2'
+BINVALUE3 = 'thedeadbeef3'
+
+USER_PROPERTIES = {
+    'uid': 'state1usr',
+    'cn': 'state1usr',
+    'sn': 'state1usr',
+    'uidNumber': '1001',
+    'gidNumber': '2001',
+    'userpassword': PASSWORD,
+    'homeDirectory': '/home/testuser'
+}
+
+
+def _check_user_oper_attrs(topo, tuser, attr_name, attr_value, oper_type, exp_values, oper_attr):
+    """Check if list of operational attributes present for a given entry"""
+
+    log.info('Checking if operational attrs vucsn, adcsn and vdcsn present for: {}'.format(tuser))
+    entry = topo.ms["master1"].search_s(tuser.dn, ldap.SCOPE_BASE, 'objectclass=*',['nscpentrywsi'])
+    if oper_attr:
+        for line in str(entry).split('\n'):
+            if attr_name + ';' in line:
+                if not 'DELETE' in oper_type:
+                    assert any(attr in line for attr in exp_values) and oper_attr in line
+                else:
+                    assert 'deleted' in line and oper_attr in line and attr_value in line
+
+
+@pytest.mark.parametrize("attr_name, attr_value, oper_type, exp_values, oper_attr",
+                         [('description', 'Test1usr1', 'ldap.MOD_ADD', ['Test1usr1'], 'vucsn'),
+                          ('description', 'Test1usr2', 'ldap.MOD_ADD', ['Test1usr1',
+                                                                        'Test1usr2'], 'vucsn'),
+                          ('description', 'Test1usr3', 'ldap.MOD_ADD',
+                           ['Test1usr1', 'Test1usr2', 'Test1usr3'], 'vucsn'),
+                          ('description', 'Test1usr4', 'ldap.MOD_REPLACE', ['Test1usr4'],
+                           'adcsn'),
+                          ('description', 'Test1usr4', 'ldap.MOD_DELETE', [], 'vdcsn')])
+def test_check_desc_attr_state(topo, attr_name, attr_value, oper_type, exp_values, oper_attr):
+    """Modify user's description attribute and check if description attribute is
+    added/modified/deleted and operational attributes vucsn, adcsn and vdcsn are present.
+
+    :id: f0830538-02cf-11e9-8be0-8c16451d917b
+    :setup: Replication with two masters.
+    :steps: 1. Add user to Master1 without description attribute.
+            2. Add description attribute to user.
+            3. Check if only one description attribute exist.
+            4. Check if operational attribute vucsn exist.
+            5. Add second description attribute to user.
+            6. Check if two description attributes exist.
+            7. Check if operational attribute vucsn exist.
+            8. Add third description attribute to user.
+            9. Check if three description attributes exist.
+            10. Check if operational attribute vucsn exist.
+            11. Replace description attribute for the user.
+            12. Check if only one description attribute exist.
+            13. Check if operational attribute adcsn exist.
+            14. Delete description attribute for the user.
+            15. Check if no description attribute exist.
+            16. Check if no operational attribute vdcsn exist.
+    :expectedresults:
+            1. Add user to M1 should PASS.
+            2. Adding description attribute should PASS
+            3. Only one description attribute should be present.
+            4. Vucsn attribute should be present.
+            5. Adding a new description attribute should PASS
+            6. Two description attribute should be present.
+            7. Vucsn attribute should be present.
+            8. Adding a new description attribute should PASS
+            9. Three description attribute should be present.
+            10. Vucsn attribute should be present.
+            11. Replacing new description attribute should PASS
+            12. Only one description attribute should be present.
+            13. Adcsn attribute should be present.
+            14. Deleting description attribute should PASS
+            15. No description attribute should be present.
+            16. Vdcsn attribute should be present.
+    """
+
+    test_entry = 'state1test'
+    log.info('Add user: {}'.format(test_entry))
+    users = UserAccounts(topo.ms['master1'], DEFAULT_SUFFIX)
+    try:
+        tuser = users.get(test_entry)
+    except ldap.NO_SUCH_OBJECT:
+        USER_PROPERTIES.update(dict.fromkeys(['uid', 'cn'], test_entry))
+        tuser = users.create(properties=USER_PROPERTIES)
+    tuser.set(attr_name, attr_value, eval(oper_type))
+    log.info('Check if list of description attrs present for: {}'.format(test_entry))
+    assert sorted([i.decode() for i in tuser.get_attr_vals(attr_name)]) == sorted(exp_values)
+
+    log.info('Checking for operational attributes')
+    _check_user_oper_attrs(topo, tuser, attr_name, attr_value, oper_type, exp_values, oper_attr)
+
+
+@pytest.mark.parametrize("attr_name, attr_value, oper_type, exp_values, oper_attr",
+                         [('cn', 'TestCN1', 'ldap.MOD_ADD', ['TestCN1', 'TestCNusr1'], 'vucsn'),
+                          ('cn', 'TestCN2', 'ldap.MOD_ADD', ['TestCN1',
+                                                             'TestCN2', 'TestCNusr1'], 'vucsn'),
+                          ('cn', 'TestnewCN3', 'ldap.MOD_REPLACE', ['TestnewCN3'], 'adcsn'),
+                          ('cn', 'TestnewCN3', 'ldap.MOD_DELETE', None, None)])
+def test_check_cn_attr_state(topo, attr_name, attr_value, oper_type, exp_values, oper_attr):
+    """Modify user's cn attribute and check if cn attribute is added/modified/deleted and
+    operational attributes vucsn, adcsn and vdcsn are present.
+
+    :id: 19614bae-02d0-11e9-a295-8c16451d917b
+    :setup: Replication with two masters.
+    :steps: 1. Add user to Master1 with cn attribute.
+            2. Add a new cn attribute to user.
+            3. Check if two cn attributes exist.
+            4. Check if operational attribute vucsn exist for each cn attribute.
+            5. Add a new cn attribute to user.
+            6. Check if three cn attributes exist.
+            7. Check if operational attribute vucsn exist for each cn attribute.
+            8. Replace cn attribute for the user.
+            9. Check if only one cn attribute exist.
+            10. Check if operational attribute adcsn exist.
+            11. Delete cn attribute from user and check if it fails.
+    :expectedresults:
+            1. Add user to M1 should PASS.
+            2. Adding a new cn attribute should PASS
+            3. Two cn attribute should be present.
+            4. Vucsn attribute should be present.
+            5. Adding a new cn attribute should PASS
+            6. Three cn attribute should be present.
+            7. Vucsn attribute should be present.
+            8. Replacing new cn attribute should PASS
+            9. Only one cn attribute should be present.
+            10. Operational attribute adcsn should be present.
+            11. Deleting cn attribute should fail with ObjectClass violation error.
+    """
+
+    test_entry = 'TestCNusr1'
+    log.info('Add user: {}'.format(test_entry))
+    users = UserAccounts(topo.ms['master1'], DEFAULT_SUFFIX)
+    try:
+        tuser = users.get(test_entry)
+    except ldap.NO_SUCH_OBJECT:
+        USER_PROPERTIES.update(dict.fromkeys(['uid', 'cn'], test_entry))
+        tuser = users.create(properties=USER_PROPERTIES)
+
+    if 'MOD_DELETE' in oper_type:
+        with pytest.raises(ldap.OBJECT_CLASS_VIOLATION):
+            tuser.set(attr_name, attr_value, eval(oper_type))
+    else:
+        tuser.set(attr_name, attr_value, eval(oper_type))
+        log.info('Check if list of cn attrs present for: {}'.format(test_entry))
+        assert sorted([i.decode() for i in tuser.get_attr_vals(attr_name)]) == sorted(exp_values)
+    log.info('Checking for operational attributes')
+    _check_user_oper_attrs(topo, tuser, attr_name, attr_value, oper_type, exp_values, oper_attr)
+
+
+@pytest.mark.parametrize("attr_name, attr_value, oper_type, exp_values, oper_attr",
+                         [('preferredlanguage', 'Chinese', 'ldap.MOD_REPLACE', ['Chinese'],
+                           'vucsn'),
+                          ('preferredlanguage', 'French', 'ldap.MOD_ADD', None, None),
+                          ('preferredlanguage', 'German', 'ldap.MOD_REPLACE', ['German'], 'adcsn'),
+                          ('preferredlanguage', 'German', 'ldap.MOD_DELETE', [], 'vdcsn')])
+def test_check_single_value_attr_state(topo, attr_name, attr_value, oper_type,
+                                       exp_values, oper_attr):
+    """Modify user's preferredlanguage attribute and check if preferredlanguage attribute is
+    added/modified/deleted and operational attributes vucsn, adcsn and vdcsn are present.
+
+    :id: 22fd645e-02d0-11e9-a9e4-8c16451d917b
+    :setup: Replication with two masters.
+    :steps: 1. Add user to Master1 without preferredlanguage attribute.
+            2. Add a new preferredlanguage attribute to user.
+            3. Check if one preferredlanguage attributes exist.
+            4. Check if operational attribute vucsn exist.
+            5. Add a new preferredlanguage attribute for the user and check if its rejected.
+            6. Replace preferredlanguage attribute for the user.
+            7. Check if only one preferredlanguage attribute exist.
+            8. Check if operational attribute adcsn exist with preferredlanguage.
+    :expectedresults:
+            1. Add user to M1 should PASS.
+            2. Adding a new preferredlanguage attribute should PASS
+            3. Only one preferredlanguage attribute should be present.
+            4. Vucsn attribute should be present.
+            5. Adding a new preferredlanguage should fail with ObjectClass violation error.
+            6. Replace preferredlanguage should PASS.
+            7. Only one preferredlanguage attribute should be present.
+            8. Operational attribute adcsn should be present with preferredlanguage.
+    """
+
+    test_entry = 'Langusr1'
+    log.info('Add user: {}'.format(test_entry))
+    users = UserAccounts(topo.ms['master1'], DEFAULT_SUFFIX)
+    try:
+        tuser = users.get(test_entry)
+    except ldap.NO_SUCH_OBJECT:
+        USER_PROPERTIES.update(dict.fromkeys(['uid', 'cn'], test_entry))
+        tuser = users.create(properties=USER_PROPERTIES)
+
+    if 'MOD_ADD' in oper_type:
+        with pytest.raises(ldap.OBJECT_CLASS_VIOLATION):
+            tuser.set(attr_name, attr_value, eval(oper_type))
+    else:
+        tuser.set(attr_name, attr_value, eval(oper_type))
+        log.info('Check if list of cn attrs present for: {}'.format(test_entry))
+        assert sorted([i.decode() for i in tuser.get_attr_vals(attr_name)]) == sorted(exp_values)
+    log.info('Checking for operational attributes')
+    _check_user_oper_attrs(topo, tuser, attr_name, attr_value, oper_type, exp_values, oper_attr)
+
+
+@pytest.mark.parametrize("attr_name, attr_value, oper_type, exp_values, oper_attr",
+                         [('roomnumber;office', 'Tower1', 'ldap.MOD_ADD', ['Tower1'], 'vucsn'),
+                          ('roomnumber;office', 'Tower2', 'ldap.MOD_ADD', ['Tower1', 'Tower2'],
+                           'vucsn'),
+                          ('roomnumber;office', 'Tower3', 'ldap.MOD_ADD', ['Tower1', 'Tower2',
+                                                                           'Tower3'], 'vucsn'),
+                          ('roomnumber;office', 'Tower4', 'ldap.MOD_REPLACE', ['Tower4'], 'adcsn'),
+                          ('roomnumber;office', 'Tower4', 'ldap.MOD_DELETE', [], 'vucsn')])
+def test_check_subtype_attr_state(topo, attr_name, attr_value, oper_type, exp_values, oper_attr):
+    """Modify user's roomnumber;office attribute subtype and check if roomnumber;office attribute
+    is added/modified/deleted and operational attributes vucsn, adcsn and vdcsn are present.
+
+    :id: 29ab87a4-02d0-11e9-b104-8c16451d917b
+    :setup: Replication with two masters.
+    :steps: 1. Add user to Master1 without roomnumber;office attribute.
+            2. Add roomnumber;office attribute to user.
+            3. Check if only one roomnumber;office attribute exist.
+            4. Check if operational attribute vucsn exist.
+            5. Add second roomnumber;office attribute to user.
+            6. Check if two roomnumber;office attributes exist.
+            7. Check if operational attribute vucsn exist.
+            8. Add third roomnumber;office attribute to user.
+            9. Check if three roomnumber;office attributes exist.
+            10. Check if operational attribute vucsn exist.
+            11. Replace roomnumber;office attribute for the user.
+            12. Check if only one roomnumber;office attribute exist.
+            13. Check if operational attribute adcsn exist.
+            14. Delete roomnumber;office attribute for the user.
+            15. Check if no roomnumber;office attribute exist.
+            16. Check if no operational attribute vdcsn exist.
+    :expectedresults:
+            1. Add user to M1 should PASS.
+            2. Adding roomnumber;office attribute should PASS
+            3. Only one roomnumber;office attribute should be present.
+            4. Vucsn attribute should be present.
+            5. Adding a new roomnumber;office attribute should PASS
+            6. Two roomnumber;office attribute should be present.
+            7. Vucsn attribute should be present.
+            8. Adding a new roomnumber;office attribute should PASS
+            9. Three roomnumber;office attribute should be present.
+            10. Vucsn attribute should be present.
+            11. Replacing new roomnumber;office attribute should PASS
+            12. Only one roomnumber;office attribute should be present.
+            13. Adcsn attribute should be present.
+            14. Deleting roomnumber;office attribute should PASS
+            15. No roomnumber;office attribute should be present.
+            16. Vdcsn attribute should be present.
+    """
+
+    test_entry = 'roomoffice1usr'
+    log.info('Add user: {}'.format(test_entry))
+    users = UserAccounts(topo.ms['master1'], DEFAULT_SUFFIX)
+    try:
+        tuser = users.get(test_entry)
+    except ldap.NO_SUCH_OBJECT:
+        USER_PROPERTIES.update(dict.fromkeys(['uid', 'cn'], test_entry))
+        tuser = users.create(properties=USER_PROPERTIES)
+
+    tuser.set(attr_name, attr_value, eval(oper_type))
+    log.info('Check if list of roomnumber;office attributes are present for a given entry')
+    assert sorted([i.decode() for i in tuser.get_attr_vals(attr_name)]) == sorted(exp_values)
+    log.info('Checking if operational attributes are present for cn')
+    _check_user_oper_attrs(topo, tuser, attr_name, attr_value, oper_type, exp_values, oper_attr)
+
+
+@pytest.mark.parametrize("attr_name, attr_value, oper_type, exp_values, oper_attr",
+                         [('jpegphoto', BINVALUE1, 'ldap.MOD_ADD', [BINVALUE1], 'vucsn'),
+                          ('jpegphoto', BINVALUE2, 'ldap.MOD_ADD', [BINVALUE1, BINVALUE2],
+                           'vucsn'),
+                          ('jpegphoto', BINVALUE3, 'ldap.MOD_ADD', [BINVALUE1, BINVALUE2,
+                                                                    BINVALUE3], 'vucsn'),
+                          ('jpegphoto', BINVALUE2, 'ldap.MOD_REPLACE', [BINVALUE2], 'adcsn'),
+                          ('jpegphoto', BINVALUE2, 'ldap.MOD_DELETE', [], 'vdcsn')])
+def test_check_jpeg_attr_state(topo, attr_name, attr_value, oper_type, exp_values, oper_attr):
+    """Modify user's jpegphoto attribute and check if jpegphoto attribute is added/modified/deleted
+    and operational attributes vucsn, adcsn and vdcsn are present.
+
+    :id: 312ac0d0-02d0-11e9-9d34-8c16451d917b
+    :setup: Replication with two masters.
+    :steps: 1. Add user to Master1 without jpegphoto attribute.
+            2. Add jpegphoto attribute to user.
+            3. Check if only one jpegphoto attribute exist.
+            4. Check if operational attribute vucsn exist.
+            5. Add second jpegphoto attribute to user.
+            6. Check if two jpegphoto attributes exist.
+            7. Check if operational attribute vucsn exist.
+            8. Add third jpegphoto attribute to user.
+            9. Check if three jpegphoto attributes exist.
+            10. Check if operational attribute vucsn exist.
+            11. Replace jpegphoto attribute for the user.
+            12. Check if only one jpegphoto attribute exist.
+            13. Check if operational attribute adcsn exist.
+            14. Delete jpegphoto attribute for the user.
+            15. Check if no jpegphoto attribute exist.
+            16. Check if no operational attribute vdcsn exist.
+    :expectedresults:
+            1. Add user to M1 should PASS.
+            2. Adding jpegphoto attribute should PASS
+            3. Only one jpegphoto attribute should be present.
+            4. Vucsn attribute should be present.
+            5. Adding a new jpegphoto attribute should PASS
+            6. Two jpegphoto attribute should be present.
+            7. Vucsn attribute should be present.
+            8. Adding a new jpegphoto attribute should PASS
+            9. Three jpegphoto attribute should be present.
+            10. Vucsn attribute should be present.
+            11. Replacing new jpegphoto attribute should PASS
+            12. Only one jpegphoto attribute should be present.
+            13. Adcsn attribute should be present.
+            14. Deleting jpegphoto attribute should PASS
+            15. No jpegphoto attribute should be present.
+            16. Vdcsn attribute should be present.
+    """
+
+    test_entry = 'testJpeg1usr'
+    log.info('Add user: {}'.format(test_entry))
+    users = UserAccounts(topo.ms['master1'], DEFAULT_SUFFIX)
+    try:
+        tuser = users.get(test_entry)
+    except ldap.NO_SUCH_OBJECT:
+        USER_PROPERTIES.update(dict.fromkeys(['uid', 'cn'], test_entry))
+        tuser = users.create(properties=USER_PROPERTIES)
+
+    tuser.set(attr_name, attr_value, eval(oper_type))
+    log.info('Check if list of jpeg attributes are present for a given entry')
+    assert sorted([i.decode() for i in tuser.get_attr_vals(attr_name)]) == sorted(exp_values)
+    log.info('Checking if operational attributes are present for cn')
+    _check_user_oper_attrs(topo, tuser, attr_name, attr_value, oper_type, exp_values, oper_attr)
+
+
+if __name__ == "__main__":
+    # Run isolated
+    # -s for DEBUG mode
+    CURRENT_FILE = os.path.realpath(__file__)
+    pytest.main("-s -v %s" % CURRENT_FILE)
\ No newline at end of file

