import logging
import pytest
import os
import ldap
import time
import sys
print(sys.path)
from lib389 import Entry
from lib389._constants import DEFAULT_SUFFIX
from lib389.idm.user import UserAccounts, TEST_USER_PROPERTIES
from lib389.topologies import topology_m3 as topo

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__)


MAX_EMPLOYEENUMBER_USER = 10
MAX_STANDARD_USER = 100
MAX_USER = MAX_STANDARD_USER + MAX_EMPLOYEENUMBER_USER
EMPLOYEENUMBER_RDN_START = 0

USER_UID='user_'
BASE_DISTINGUISHED = 'ou=distinguished,ou=people,%s' % (DEFAULT_SUFFIX)
BASE_REGULAR = 'ou=regular,ou=people,%s' % (DEFAULT_SUFFIX)

def _user_get_dn(no):
    uid = '%s%d' % (USER_UID, no)
    dn = 'uid=%s,%s' % (uid, BASE_REGULAR)
    return (uid, dn)

def add_user(server, no, init_val):
    (uid, dn) = _user_get_dn(no)
    log.fatal('Adding user (%s): ' % dn)
    server.add_s(Entry((dn, {'objectclass': ['top', 'person', 'organizationalPerson', 'inetOrgPerson'],
                             'uid': [uid],
                             'sn' : [uid],
                             'cn' : [uid],
                             'employeeNumber': init_val})))
    return dn

def _employeenumber_user_get_dn(no):
    employeeNumber = str(no)
    dn = 'employeeNumber=%s,%s' % (employeeNumber, BASE_DISTINGUISHED)
    return (employeeNumber, dn)

def add_employeenumber_user(server, no):
    (uid, dn) = _employeenumber_user_get_dn(EMPLOYEENUMBER_RDN_START + no)
    log.fatal('Adding user (%s): ' % dn)
    server.add_s(Entry((dn, {'objectclass': ['top', 'person', 'organizationalPerson', 'inetOrgPerson'],
                             'uid': [uid],
                             'sn' : [uid],
                             'cn' : [uid],
                             'employeeNumber': str(EMPLOYEENUMBER_RDN_START + no)})))
    return dn


def test_ticket49658_init(topo):
    """Specify a test case purpose or name here

    :id: 0
    :setup: 3 Master Instances
    :steps:
        1. Create 3 suppliers
        2. Create on M3 MAX_USER test entries having a single-value attribute employeeNumber=11
            and update it MOD_DEL 11 + MOD_ADD 1000
        3. Check they are replicated on M1 and M2
    :expectedresults:
        1. Fill in the result that is expected
        2. For each test step
    """

    # If you need any test suite initialization,
    # please, write additional fixture for that (including finalizer).
    # Topology for suites are predefined in lib389/topologies.py.

    # If you need host, port or any other data about instance,
    # Please, use the instance object attributes for that (for example, topo.ms["master1"].serverid)

    if DEBUGGING:
        # Add debugging steps(if any)...
        pass
    M1 = topo.ms["master1"]
    M2 = topo.ms["master2"]
    M3 = topo.ms["master3"]
    value_11 = '11'.encode()
    value_1000 = '1000'.encode()
    
    # Step 2
    M3.add_s(Entry((BASE_DISTINGUISHED, {'objectclass': ['top', 'organizationalUnit'],
                             'ou': ['distinguished']})))
    for i in range(MAX_EMPLOYEENUMBER_USER):
        test_user_dn= add_employeenumber_user(M3, i)
        log.info('Adding %s on M3' % test_user_dn)
        ents = M3.search_s(DEFAULT_SUFFIX, ldap.SCOPE_SUBTREE, '(employeeNumber=*)')
        assert len(ents) == (i + 1)
        
    M3.add_s(Entry((BASE_REGULAR, {'objectclass': ['top', 'organizationalUnit'],
                             'ou': ['regular']})))
    for i in range(MAX_STANDARD_USER):
        test_user_dn= add_user(M3, i, value_11)
        log.info('Adding %s on M3' % test_user_dn)
        M3.modify_s(test_user_dn, [(ldap.MOD_DELETE, 'employeeNumber', value_11), (ldap.MOD_ADD, 'employeeNumber', value_1000)])
        ents = M3.search_s(DEFAULT_SUFFIX, ldap.SCOPE_SUBTREE, '(employeeNumber=*)')
        assert len(ents) == (MAX_EMPLOYEENUMBER_USER + i + 1)
    
    
    # Step 3
    # Check the last entry is replicated on M1
    (uid, test_user_dn) = _user_get_dn(MAX_STANDARD_USER - 1)
    for j in range(30):
            try:
                ent = M1.getEntry(test_user_dn, ldap.SCOPE_BASE,)
                if not ent.hasAttr('employeeNumber'):
                    # wait for the MOD
                    log.info('M1 waiting for employeeNumber')
                    time.sleep(1)
                    continue;
                break;
            except ldap.NO_SUCH_OBJECT:
                time.sleep(1)
                pass
    time.sleep(1)
    ents = M1.search_s(DEFAULT_SUFFIX, ldap.SCOPE_SUBTREE, '(employeeNumber=*)')
    assert len(ents) == MAX_USER
                
    # Check the last entry is replicated on M2
    for j in range(30):
            try:
                ent = M2.getEntry(test_user_dn, ldap.SCOPE_BASE,)
                if not ent.hasAttr('employeeNumber'):
                    # wait for the MOD
                    log.info('M2 waiting for employeeNumber')
                    time.sleep(1)
                    continue;

                break;
            except ldap.NO_SUCH_OBJECT:
                time.sleep(1)
                pass
    time.sleep(1)
    ents = M2.search_s(DEFAULT_SUFFIX, ldap.SCOPE_SUBTREE, '(employeeNumber=*)')
    assert len(ents) == MAX_USER

def test_ticket49658_18(topo):
    """Do 
        M1: MODRDN    -> V1
        M2: MODRDN    -> V2
        M1: MOD(REPL) -> V1
        Replicate:
            M2
            M1
        expected: V2

    :id: 16
    :setup: 3 Master Instances
        1. Use employeenumber=1000,ou=distinguished,ou=people,<suffix>
    :steps:
        1. Isolate M1 and M2 by pausing the replication agreements
        2. On M1 do DEL+ADD 1000 + MOD_ADD_13
        3. On M2 do DEL+ADD 1000 + MOD_ADD_13
        4. Enable replication agreement M2 -> M3, so that update step 2 is replicated first
        5. Enable replication agreement M1 -> M3, so that update step 3 is replicated second
        6. Check that the employeeNumber is 13 on all servers
    :expectedresults:
        1. Fill in the result that is expected
        2. For each test step
    """

    # If you need any test suite initialization,
    # please, write additional fixture for that (including finalizer).
    # Topology for suites are predefined in lib389/topologies.py.

    # If you need host, port or any other data about instance,
    # Please, use the instance object attributes for that (for example, topo.ms["master1"].serverid)
    


    if DEBUGGING:
        # Add debugging steps(if any)...
        pass
    M1 = topo.ms["master1"]
    M2 = topo.ms["master2"]
    M3 = topo.ms["master3"]
    value_init = '3'
    last = '3'
    value_S1 = '3.1'
    value_S2 = '3.2'
    
    description = {
    "S1": M1,
    "S2": M2,
    "S1_MODRDN": value_S1,
    "S1_MOD": [(ldap.MOD_REPLACE, 'employeeNumber', value_S1.encode())],
    "S2_MODRDN": value_S2,
    "expected": value_S2}
    
    # This test takes the user_1
    (uid, test_user_dn) = _employeenumber_user_get_dn(int(last))
    
    #
    # Step 4
    #
    # disable all RA from M1 and M2
    # only M3 can replicate the update
    #
    agreement_m1_m2 = M1.agreement.list(suffix=DEFAULT_SUFFIX, consumer_host=M2.host, consumer_port=M2.port)
    agreement_m1_m3 = M1.agreement.list(suffix=DEFAULT_SUFFIX, consumer_host=M3.host, consumer_port=M3.port)
    agreement_m2_m1 = M2.agreement.list(suffix=DEFAULT_SUFFIX, consumer_host=M1.host, consumer_port=M1.port)
    agreement_m2_m3 = M2.agreement.list(suffix=DEFAULT_SUFFIX, consumer_host=M3.host, consumer_port=M3.port)
    
    M1.agreement.pause(agreement_m1_m2[0].dn)
    M1.agreement.pause(agreement_m1_m3[0].dn)
    M2.agreement.pause(agreement_m2_m1[0].dn)
    M2.agreement.pause(agreement_m2_m3[0].dn)

    # Step 5
    # Oldest update
    # check that the entry on M1 contains employeeNumber=<value_end>
    description["S1"].rename_s(test_user_dn, 'employeeNumber=%s' % description["S1_MODRDN"], newsuperior=BASE_DISTINGUISHED, delold=1)
    ents = description["S1"].search_s(BASE_DISTINGUISHED, ldap.SCOPE_SUBTREE, '(employeeNumber=%s)' % description["S1_MODRDN"])
    assert len(ents) == 1
    time.sleep(1)
    
    # Step 6
    # More recent update
    # check that the entry on M2 contains employeeNumber=<value_end>
    description["S2"].rename_s(test_user_dn, 'employeeNumber=%s' % description["S2_MODRDN"], newsuperior=BASE_DISTINGUISHED, delold=1)
    ents = description["S2"].search_s(BASE_DISTINGUISHED, ldap.SCOPE_SUBTREE, '(employeeNumber=%s)' % description["S2_MODRDN"])
    assert len(ents) == 1
    time.sleep(1)

    (no, new_test_user_dn) = _employeenumber_user_get_dn(description["S1_MODRDN"])
    description["S1"].modify_s(new_test_user_dn, description["S1_MOD"])
    ents = description["S1"].search_s(BASE_DISTINGUISHED, ldap.SCOPE_SUBTREE, '(employeeNumber=%s)' % value_S1)
    assert len(ents) == 1

    #time.sleep(60)
    # Step 7
    # Renable M2 before M1 so that on M3, the most recent update is replicated before
    for ra in agreement_m2_m1, agreement_m2_m3:
        M2.agreement.resume(ra[0].dn)
        
    # Step 8
    # Renable M1 so that on M3 oldest update is now replicated
    time.sleep(4)
    for ra in agreement_m1_m2, agreement_m1_m3:
        M1.agreement.resume(ra[0].dn)
    
    #time.sleep(3600)
    # Step 9
    # Check that M1 still contains employeeNumber=<value_end>
    ents = M1.search_s(BASE_DISTINGUISHED, ldap.SCOPE_SUBTREE, '(employeeNumber=%s)' % description["expected"])
    log.info('Search M1 employeeNumber=%s (vs. %s)' % (ents[0].getValue('employeeNumber'), description["expected"]))
    assert len(ents) == 1
    assert ents[0].hasAttr('employeeNumber') and ents[0].getValue('employeeNumber') == description["expected"].encode()
        
    # Check that M2 still contains employeeNumber=<value_end>
    ents = M2.search_s(BASE_DISTINGUISHED, ldap.SCOPE_SUBTREE, '(employeeNumber=%s)' % description["expected"])
    log.info('Search M2 employeeNumber=%s (vs. %s)' % (ents[0].getValue('employeeNumber'), description["expected"]))
    assert len(ents) == 1
    assert ents[0].hasAttr('employeeNumber') and ents[0].getValue('employeeNumber') == description["expected"].encode()
    
    # Check that M3 still contain employeeNumber and it contains employeeNumber=<value_end>
    ents = M3.search_s(BASE_DISTINGUISHED, ldap.SCOPE_SUBTREE, '(employeeNumber=*)')
    assert len(ents) == MAX_EMPLOYEENUMBER_USER
    ents = M3.search_s(BASE_DISTINGUISHED, ldap.SCOPE_SUBTREE, '(employeeNumber=%s)' % description["expected"])
    log.info('Search M3 employeeNumber=%s (vs. %s)' % (ents[0].getValue('employeeNumber'), description["expected"]))
    assert len(ents) == 1
    assert ents[0].hasAttr('employeeNumber') and ents[0].getValue('employeeNumber') == description["expected"].encode()

def test_ticket49658_19(topo):
    """Do 
        M1: MODRDN    -> V1
        M2: MODRDN    -> V2
        M1: MOD(REPL) -> V1
        Replicate:
            M1
            M2
        expected: V2

    :id: 16
    :setup: 3 Master Instances
        1. Use employeenumber=1000,ou=distinguished,ou=people,<suffix>
    :steps:
        1. Isolate M1 and M2 by pausing the replication agreements
        2. On M1 do DEL+ADD 1000 + MOD_ADD_13
        3. On M2 do DEL+ADD 1000 + MOD_ADD_13
        4. Enable replication agreement M2 -> M3, so that update step 2 is replicated first
        5. Enable replication agreement M1 -> M3, so that update step 3 is replicated second
        6. Check that the employeeNumber is 13 on all servers
    :expectedresults:
        1. Fill in the result that is expected
        2. For each test step
    """

    # If you need any test suite initialization,
    # please, write additional fixture for that (including finalizer).
    # Topology for suites are predefined in lib389/topologies.py.

    # If you need host, port or any other data about instance,
    # Please, use the instance object attributes for that (for example, topo.ms["master1"].serverid)
    


    if DEBUGGING:
        # Add debugging steps(if any)...
        pass
    M1 = topo.ms["master1"]
    M2 = topo.ms["master2"]
    M3 = topo.ms["master3"]
    value_init = '3'
    last = '4'
    value_S1 = '4.1'
    value_S2 = '4.2'
    
    description = {
    "S1": M1,
    "S2": M2,
    "S1_MODRDN": value_S1,
    "S1_MOD": [(ldap.MOD_REPLACE, 'employeeNumber', value_S1.encode())],
    "S2_MODRDN": value_S2,
    "expected": value_S2}
    
    # This test takes the user_1
    (uid, test_user_dn) = _employeenumber_user_get_dn(int(last))
    
    #
    # Step 4
    #
    # disable all RA from M1 and M2
    # only M3 can replicate the update
    #
    agreement_m1_m2 = M1.agreement.list(suffix=DEFAULT_SUFFIX, consumer_host=M2.host, consumer_port=M2.port)
    agreement_m1_m3 = M1.agreement.list(suffix=DEFAULT_SUFFIX, consumer_host=M3.host, consumer_port=M3.port)
    agreement_m2_m1 = M2.agreement.list(suffix=DEFAULT_SUFFIX, consumer_host=M1.host, consumer_port=M1.port)
    agreement_m2_m3 = M2.agreement.list(suffix=DEFAULT_SUFFIX, consumer_host=M3.host, consumer_port=M3.port)
    
    M1.agreement.pause(agreement_m1_m2[0].dn)
    M1.agreement.pause(agreement_m1_m3[0].dn)
    M2.agreement.pause(agreement_m2_m1[0].dn)
    M2.agreement.pause(agreement_m2_m3[0].dn)

    # Step 5
    # Oldest update
    # check that the entry on M1 contains employeeNumber=<value_end>
    description["S1"].rename_s(test_user_dn, 'employeeNumber=%s' % description["S1_MODRDN"], newsuperior=BASE_DISTINGUISHED, delold=1)
    ents = description["S1"].search_s(BASE_DISTINGUISHED, ldap.SCOPE_SUBTREE, '(employeeNumber=%s)' % description["S1_MODRDN"])
    assert len(ents) == 1
    time.sleep(1)
    
    # Step 6
    # More recent update
    # check that the entry on M2 contains employeeNumber=<value_end>
    description["S2"].rename_s(test_user_dn, 'employeeNumber=%s' % description["S2_MODRDN"], newsuperior=BASE_DISTINGUISHED, delold=1)
    ents = description["S2"].search_s(BASE_DISTINGUISHED, ldap.SCOPE_SUBTREE, '(employeeNumber=%s)' % description["S2_MODRDN"])
    assert len(ents) == 1
    time.sleep(1)

    (no, new_test_user_dn) = _employeenumber_user_get_dn(description["S1_MODRDN"])
    description["S1"].modify_s(new_test_user_dn, description["S1_MOD"])
    ents = description["S1"].search_s(BASE_DISTINGUISHED, ldap.SCOPE_SUBTREE, '(employeeNumber=%s)' % value_S1)
    assert len(ents) == 1

    #time.sleep(60)
    # Step 7
    # Renable M2 before M1 so that on M3, the most recent update is replicated before
    for ra in agreement_m1_m2, agreement_m1_m3:
        M1.agreement.resume(ra[0].dn)
        
        
    # Step 8
    # Renable M1 so that on M3 oldest update is now replicated
    time.sleep(4)
    for ra in agreement_m2_m1, agreement_m2_m3:
        M2.agreement.resume(ra[0].dn)
    
    #time.sleep(3600)
    # Step 9
    # Check that M1 still contains employeeNumber=<value_end>
    ents = M1.search_s(BASE_DISTINGUISHED, ldap.SCOPE_SUBTREE, '(employeeNumber=%s)' % description["expected"])
    log.info('Search M1 employeeNumber=%s (vs. %s)' % (ents[0].getValue('employeeNumber'), description["expected"]))
    assert len(ents) == 1
    assert ents[0].hasAttr('employeeNumber') and ents[0].getValue('employeeNumber') == description["expected"].encode()
        
    # Check that M2 still contains employeeNumber=<value_end>
    ents = M2.search_s(BASE_DISTINGUISHED, ldap.SCOPE_SUBTREE, '(employeeNumber=%s)' % description["expected"])
    log.info('Search M2 employeeNumber=%s (vs. %s)' % (ents[0].getValue('employeeNumber'), description["expected"]))
    assert len(ents) == 1
    assert ents[0].hasAttr('employeeNumber') and ents[0].getValue('employeeNumber') == description["expected"].encode()
    
    # Check that M3 still contain employeeNumber and it contains employeeNumber=<value_end>
    ents = M3.search_s(BASE_DISTINGUISHED, ldap.SCOPE_SUBTREE, '(employeeNumber=*)')
    assert len(ents) == MAX_EMPLOYEENUMBER_USER
    ents = M3.search_s(BASE_DISTINGUISHED, ldap.SCOPE_SUBTREE, '(employeeNumber=%s)' % description["expected"])
    log.info('Search M3 employeeNumber=%s (vs. %s)' % (ents[0].getValue('employeeNumber'), description["expected"]))
    assert len(ents) == 1
    assert ents[0].hasAttr('employeeNumber') and ents[0].getValue('employeeNumber') == description["expected"].encode()

def test_ticket49658_20(topo):
    """Do 
        M1: MODRDN    -> V1
        M2: MODRDN    -> V2
        M1: MOD(DEL/ADD) -> V1
        Replicate:
            M2
            M1
        expected: V2

    :id: 16
    :setup: 3 Master Instances
        1. Use employeenumber=1000,ou=distinguished,ou=people,<suffix>
    :steps:
        1. Isolate M1 and M2 by pausing the replication agreements
        2. On M1 do DEL+ADD 1000 + MOD_ADD_13
        3. On M2 do DEL+ADD 1000 + MOD_ADD_13
        4. Enable replication agreement M2 -> M3, so that update step 2 is replicated first
        5. Enable replication agreement M1 -> M3, so that update step 3 is replicated second
        6. Check that the employeeNumber is 13 on all servers
    :expectedresults:
        1. Fill in the result that is expected
        2. For each test step
    """

    # If you need any test suite initialization,
    # please, write additional fixture for that (including finalizer).
    # Topology for suites are predefined in lib389/topologies.py.

    # If you need host, port or any other data about instance,
    # Please, use the instance object attributes for that (for example, topo.ms["master1"].serverid)
    


    if DEBUGGING:
        # Add debugging steps(if any)...
        pass
    M1 = topo.ms["master1"]
    M2 = topo.ms["master2"]
    M3 = topo.ms["master3"]
    value_init = '3'
    last = '5'
    value_S1 = '5.1'
    value_S2 = '5.2'
    
    description = {
    "S1": M1,
    "S2": M2,
    "S1_MODRDN": value_S1,
    "S1_MOD": [(ldap.MOD_DELETE, 'employeeNumber', value_S1.encode()),(ldap.MOD_ADD, 'employeeNumber', value_S1.encode())],
    "S2_MODRDN": value_S2,
    "expected": value_S2}
    
    # This test takes the user_1
    (uid, test_user_dn) = _employeenumber_user_get_dn(int(last))
    
    #
    # Step 4
    #
    # disable all RA from M1 and M2
    # only M3 can replicate the update
    #
    agreement_m1_m2 = M1.agreement.list(suffix=DEFAULT_SUFFIX, consumer_host=M2.host, consumer_port=M2.port)
    agreement_m1_m3 = M1.agreement.list(suffix=DEFAULT_SUFFIX, consumer_host=M3.host, consumer_port=M3.port)
    agreement_m2_m1 = M2.agreement.list(suffix=DEFAULT_SUFFIX, consumer_host=M1.host, consumer_port=M1.port)
    agreement_m2_m3 = M2.agreement.list(suffix=DEFAULT_SUFFIX, consumer_host=M3.host, consumer_port=M3.port)
    
    M1.agreement.pause(agreement_m1_m2[0].dn)
    M1.agreement.pause(agreement_m1_m3[0].dn)
    M2.agreement.pause(agreement_m2_m1[0].dn)
    M2.agreement.pause(agreement_m2_m3[0].dn)

    # Step 5
    # Oldest update
    # check that the entry on M1 contains employeeNumber=<value_end>
    description["S1"].rename_s(test_user_dn, 'employeeNumber=%s' % description["S1_MODRDN"], newsuperior=BASE_DISTINGUISHED, delold=1)
    ents = description["S1"].search_s(BASE_DISTINGUISHED, ldap.SCOPE_SUBTREE, '(employeeNumber=%s)' % description["S1_MODRDN"])
    assert len(ents) == 1
    time.sleep(1)
    
    # Step 6
    # More recent update
    # check that the entry on M2 contains employeeNumber=<value_end>
    description["S2"].rename_s(test_user_dn, 'employeeNumber=%s' % description["S2_MODRDN"], newsuperior=BASE_DISTINGUISHED, delold=1)
    ents = description["S2"].search_s(BASE_DISTINGUISHED, ldap.SCOPE_SUBTREE, '(employeeNumber=%s)' % description["S2_MODRDN"])
    assert len(ents) == 1
    time.sleep(1)

    (no, new_test_user_dn) = _employeenumber_user_get_dn(description["S1_MODRDN"])
    description["S1"].modify_s(new_test_user_dn, description["S1_MOD"])
    ents = description["S1"].search_s(BASE_DISTINGUISHED, ldap.SCOPE_SUBTREE, '(employeeNumber=%s)' % value_S1)
    assert len(ents) == 1

    #time.sleep(60)
    # Step 7
    # Renable M2 before M1 so that on M3, the most recent update is replicated before
    for ra in agreement_m2_m1, agreement_m2_m3:
        M2.agreement.resume(ra[0].dn)
        
    # Step 8
    # Renable M1 so that on M3 oldest update is now replicated
    time.sleep(4)
    for ra in agreement_m1_m2, agreement_m1_m3:
        M1.agreement.resume(ra[0].dn)
    
    #time.sleep(3600)
    # Step 9
    # Check that M1 still contains employeeNumber=<value_end>
    ents = M1.search_s(BASE_DISTINGUISHED, ldap.SCOPE_SUBTREE, '(employeeNumber=%s)' % description["expected"])
    log.info('Search M1 employeeNumber=%s (vs. %s)' % (ents[0].getValue('employeeNumber'), description["expected"]))
    assert len(ents) == 1
    assert ents[0].hasAttr('employeeNumber') and ents[0].getValue('employeeNumber') == description["expected"].encode()
        
    # Check that M2 still contains employeeNumber=<value_end>
    ents = M2.search_s(BASE_DISTINGUISHED, ldap.SCOPE_SUBTREE, '(employeeNumber=%s)' % description["expected"])
    log.info('Search M2 employeeNumber=%s (vs. %s)' % (ents[0].getValue('employeeNumber'), description["expected"]))
    assert len(ents) == 1
    assert ents[0].hasAttr('employeeNumber') and ents[0].getValue('employeeNumber') == description["expected"].encode()
    
    # Check that M3 still contain employeeNumber and it contains employeeNumber=<value_end>
    ents = M3.search_s(BASE_DISTINGUISHED, ldap.SCOPE_SUBTREE, '(employeeNumber=*)')
    assert len(ents) == MAX_EMPLOYEENUMBER_USER
    ents = M3.search_s(BASE_DISTINGUISHED, ldap.SCOPE_SUBTREE, '(employeeNumber=%s)' % description["expected"])
    log.info('Search M3 employeeNumber=%s (vs. %s)' % (ents[0].getValue('employeeNumber'), description["expected"]))
    assert len(ents) == 1
    assert ents[0].hasAttr('employeeNumber') and ents[0].getValue('employeeNumber') == description["expected"].encode()

def test_ticket49658_21(topo):
    """Do 
        M1: MODRDN    -> V1
        M2: MODRDN    -> V2
        M1: MOD(DEL/ADD) -> V1
        Replicate:
            M1
            M2
        expected: V2

    :id: 16
    :setup: 3 Master Instances
        1. Use employeenumber=1000,ou=distinguished,ou=people,<suffix>
    :steps:
        1. Isolate M1 and M2 by pausing the replication agreements
        2. On M1 do DEL+ADD 1000 + MOD_ADD_13
        3. On M2 do DEL+ADD 1000 + MOD_ADD_13
        4. Enable replication agreement M2 -> M3, so that update step 2 is replicated first
        5. Enable replication agreement M1 -> M3, so that update step 3 is replicated second
        6. Check that the employeeNumber is 13 on all servers
    :expectedresults:
        1. Fill in the result that is expected
        2. For each test step
    """

    # If you need any test suite initialization,
    # please, write additional fixture for that (including finalizer).
    # Topology for suites are predefined in lib389/topologies.py.

    # If you need host, port or any other data about instance,
    # Please, use the instance object attributes for that (for example, topo.ms["master1"].serverid)
    


    if DEBUGGING:
        # Add debugging steps(if any)...
        pass
    M1 = topo.ms["master1"]
    M2 = topo.ms["master2"]
    M3 = topo.ms["master3"]
    value_init = '3'
    last = '6'
    value_S1 = '6.1'
    value_S2 = '6.2'
    
    description = {
    "S1": M1,
    "S2": M2,
    "S1_MODRDN": value_S1,
    "S1_MOD": [(ldap.MOD_DELETE, 'employeeNumber', value_S1.encode()),(ldap.MOD_ADD, 'employeeNumber', value_S1.encode())],
    "S2_MODRDN": value_S2,
    "expected": value_S2}
    
    # This test takes the user_1
    (uid, test_user_dn) = _employeenumber_user_get_dn(int(last))
    
    #
    # Step 4
    #
    # disable all RA from M1 and M2
    # only M3 can replicate the update
    #
    agreement_m1_m2 = M1.agreement.list(suffix=DEFAULT_SUFFIX, consumer_host=M2.host, consumer_port=M2.port)
    agreement_m1_m3 = M1.agreement.list(suffix=DEFAULT_SUFFIX, consumer_host=M3.host, consumer_port=M3.port)
    agreement_m2_m1 = M2.agreement.list(suffix=DEFAULT_SUFFIX, consumer_host=M1.host, consumer_port=M1.port)
    agreement_m2_m3 = M2.agreement.list(suffix=DEFAULT_SUFFIX, consumer_host=M3.host, consumer_port=M3.port)
    
    M1.agreement.pause(agreement_m1_m2[0].dn)
    M1.agreement.pause(agreement_m1_m3[0].dn)
    M2.agreement.pause(agreement_m2_m1[0].dn)
    M2.agreement.pause(agreement_m2_m3[0].dn)

    # Step 5
    # Oldest update
    # check that the entry on M1 contains employeeNumber=<value_end>
    description["S1"].rename_s(test_user_dn, 'employeeNumber=%s' % description["S1_MODRDN"], newsuperior=BASE_DISTINGUISHED, delold=1)
    ents = description["S1"].search_s(BASE_DISTINGUISHED, ldap.SCOPE_SUBTREE, '(employeeNumber=%s)' % description["S1_MODRDN"])
    assert len(ents) == 1
    time.sleep(1)
    
    # Step 6
    # More recent update
    # check that the entry on M2 contains employeeNumber=<value_end>
    description["S2"].rename_s(test_user_dn, 'employeeNumber=%s' % description["S2_MODRDN"], newsuperior=BASE_DISTINGUISHED, delold=1)
    ents = description["S2"].search_s(BASE_DISTINGUISHED, ldap.SCOPE_SUBTREE, '(employeeNumber=%s)' % description["S2_MODRDN"])
    assert len(ents) == 1
    time.sleep(1)

    (no, new_test_user_dn) = _employeenumber_user_get_dn(description["S1_MODRDN"])
    description["S1"].modify_s(new_test_user_dn, description["S1_MOD"])
    ents = description["S1"].search_s(BASE_DISTINGUISHED, ldap.SCOPE_SUBTREE, '(employeeNumber=%s)' % value_S1)
    assert len(ents) == 1

    #time.sleep(60)
    # Step 7
    # Renable M2 before M1 so that on M3, the most recent update is replicated before
    for ra in agreement_m1_m2, agreement_m1_m3:
        M1.agreement.resume(ra[0].dn)
        
    # Step 8
    # Renable M1 so that on M3 oldest update is now replicated
    time.sleep(4)
    for ra in agreement_m2_m1, agreement_m2_m3:
        M2.agreement.resume(ra[0].dn)
    
    #time.sleep(3600)
    # Step 9
    # Check that M1 still contains employeeNumber=<value_end>
    ents = M1.search_s(BASE_DISTINGUISHED, ldap.SCOPE_SUBTREE, '(employeeNumber=%s)' % description["expected"])
    log.info('Search M1 employeeNumber=%s (vs. %s)' % (ents[0].getValue('employeeNumber'), description["expected"]))
    assert len(ents) == 1
    assert ents[0].hasAttr('employeeNumber') and ents[0].getValue('employeeNumber') == description["expected"].encode()
        
    # Check that M2 still contains employeeNumber=<value_end>
    ents = M2.search_s(BASE_DISTINGUISHED, ldap.SCOPE_SUBTREE, '(employeeNumber=%s)' % description["expected"])
    log.info('Search M2 employeeNumber=%s (vs. %s)' % (ents[0].getValue('employeeNumber'), description["expected"]))
    assert len(ents) == 1
    assert ents[0].hasAttr('employeeNumber') and ents[0].getValue('employeeNumber') == description["expected"].encode()
    
    # Check that M3 still contain employeeNumber and it contains employeeNumber=<value_end>
    ents = M3.search_s(BASE_DISTINGUISHED, ldap.SCOPE_SUBTREE, '(employeeNumber=*)')
    assert len(ents) == MAX_EMPLOYEENUMBER_USER
    ents = M3.search_s(BASE_DISTINGUISHED, ldap.SCOPE_SUBTREE, '(employeeNumber=%s)' % description["expected"])
    log.info('Search M3 employeeNumber=%s (vs. %s)' % (ents[0].getValue('employeeNumber'), description["expected"]))
    assert len(ents) == 1
    assert ents[0].hasAttr('employeeNumber') and ents[0].getValue('employeeNumber') == description["expected"].encode()

def test_ticket49658_22(topo):
    """Do 
        M1: MODRDN    -> V1
        M2: MODRDN    -> V2
        M1: MOD(REPL) -> V1
        M2: MOD(REPL) -> V2
        Replicate:
            M2
            M1
        expected: V2

    :id: 16
    :setup: 3 Master Instances
        1. Use employeenumber=1000,ou=distinguished,ou=people,<suffix>
    :steps:
        1. Isolate M1 and M2 by pausing the replication agreements
        2. On M1 do DEL+ADD 1000 + MOD_ADD_13
        3. On M2 do DEL+ADD 1000 + MOD_ADD_13
        4. Enable replication agreement M2 -> M3, so that update step 2 is replicated first
        5. Enable replication agreement M1 -> M3, so that update step 3 is replicated second
        6. Check that the employeeNumber is 13 on all servers
    :expectedresults:
        1. Fill in the result that is expected
        2. For each test step
    """

    # If you need any test suite initialization,
    # please, write additional fixture for that (including finalizer).
    # Topology for suites are predefined in lib389/topologies.py.

    # If you need host, port or any other data about instance,
    # Please, use the instance object attributes for that (for example, topo.ms["master1"].serverid)
    


    if DEBUGGING:
        # Add debugging steps(if any)...
        pass
    M1 = topo.ms["master1"]
    M2 = topo.ms["master2"]
    M3 = topo.ms["master3"]
    value_init = '7'
    last = '7'
    value_S1 = '7.1'
    value_S2 = '7.2'
    
    description = {
    "S1": M1,
    "S2": M2,
    "S1_MODRDN": value_S1,
    "S1_MOD": [(ldap.MOD_REPLACE, 'employeeNumber', value_S1.encode())],
    "S2_MOD": [(ldap.MOD_REPLACE, 'employeeNumber', value_S2.encode())],
    "S2_MODRDN": value_S2,
    "expected": value_S2}
    
    # This test takes the user_1
    (uid, test_user_dn) = _employeenumber_user_get_dn(int(last))
    
    #
    # Step 4
    #
    # disable all RA from M1 and M2
    # only M3 can replicate the update
    #
    agreement_m1_m2 = M1.agreement.list(suffix=DEFAULT_SUFFIX, consumer_host=M2.host, consumer_port=M2.port)
    agreement_m1_m3 = M1.agreement.list(suffix=DEFAULT_SUFFIX, consumer_host=M3.host, consumer_port=M3.port)
    agreement_m2_m1 = M2.agreement.list(suffix=DEFAULT_SUFFIX, consumer_host=M1.host, consumer_port=M1.port)
    agreement_m2_m3 = M2.agreement.list(suffix=DEFAULT_SUFFIX, consumer_host=M3.host, consumer_port=M3.port)
    
    M1.agreement.pause(agreement_m1_m2[0].dn)
    M1.agreement.pause(agreement_m1_m3[0].dn)
    M2.agreement.pause(agreement_m2_m1[0].dn)
    M2.agreement.pause(agreement_m2_m3[0].dn)

    # Step 5
    # Oldest update
    # check that the entry on M1 contains employeeNumber=<value_end>
    description["S1"].rename_s(test_user_dn, 'employeeNumber=%s' % description["S1_MODRDN"], newsuperior=BASE_DISTINGUISHED, delold=1)
    ents = description["S1"].search_s(BASE_DISTINGUISHED, ldap.SCOPE_SUBTREE, '(employeeNumber=%s)' % description["S1_MODRDN"])
    assert len(ents) == 1
    time.sleep(1)
    
    # Step 6
    # More recent update
    # check that the entry on M2 contains employeeNumber=<value_end>
    description["S2"].rename_s(test_user_dn, 'employeeNumber=%s' % description["S2_MODRDN"], newsuperior=BASE_DISTINGUISHED, delold=1)
    ents = description["S2"].search_s(BASE_DISTINGUISHED, ldap.SCOPE_SUBTREE, '(employeeNumber=%s)' % description["S2_MODRDN"])
    assert len(ents) == 1
    time.sleep(1)

    (no, new_test_user_dn) = _employeenumber_user_get_dn(description["S1_MODRDN"])
    description["S1"].modify_s(new_test_user_dn, description["S1_MOD"])
    ents = description["S1"].search_s(BASE_DISTINGUISHED, ldap.SCOPE_SUBTREE, '(employeeNumber=%s)' % value_S1)
    assert len(ents) == 1
    time.sleep(1)

    (no, new_test_user_dn) = _employeenumber_user_get_dn(description["S2_MODRDN"])
    description["S2"].modify_s(new_test_user_dn, description["S2_MOD"])
    ents = description["S2"].search_s(BASE_DISTINGUISHED, ldap.SCOPE_SUBTREE, '(employeeNumber=%s)' % value_S2)
    assert len(ents) == 1

    #time.sleep(60)
    # Step 7
    # Renable M2 before M1 so that on M3, the most recent update is replicated before
    for ra in agreement_m2_m1, agreement_m2_m3:
        M2.agreement.resume(ra[0].dn)
        
    # Step 8
    # Renable M1 so that on M3 oldest update is now replicated
    time.sleep(4)
    for ra in agreement_m1_m2, agreement_m1_m3:
        M1.agreement.resume(ra[0].dn)
    
    #time.sleep(3600)
    # Step 9
    # Check that M1 still contains employeeNumber=<value_end>
    ents = M1.search_s(BASE_DISTINGUISHED, ldap.SCOPE_SUBTREE, '(employeeNumber=%s)' % description["expected"])
    log.info('Search M1 employeeNumber=%s (vs. %s)' % (ents[0].getValue('employeeNumber'), description["expected"]))
    assert len(ents) == 1
    assert ents[0].hasAttr('employeeNumber') and ents[0].getValue('employeeNumber') == description["expected"].encode()
        
    # Check that M2 still contains employeeNumber=<value_end>
    ents = M2.search_s(BASE_DISTINGUISHED, ldap.SCOPE_SUBTREE, '(employeeNumber=%s)' % description["expected"])
    log.info('Search M2 employeeNumber=%s (vs. %s)' % (ents[0].getValue('employeeNumber'), description["expected"]))
    assert len(ents) == 1
    assert ents[0].hasAttr('employeeNumber') and ents[0].getValue('employeeNumber') == description["expected"].encode()
    
    # Check that M3 still contain employeeNumber and it contains employeeNumber=<value_end>
    ents = M3.search_s(BASE_DISTINGUISHED, ldap.SCOPE_SUBTREE, '(employeeNumber=*)')
    assert len(ents) == MAX_EMPLOYEENUMBER_USER
    ents = M3.search_s(BASE_DISTINGUISHED, ldap.SCOPE_SUBTREE, '(employeeNumber=%s)' % description["expected"])
    log.info('Search M3 employeeNumber=%s (vs. %s)' % (ents[0].getValue('employeeNumber'), description["expected"]))
    assert len(ents) == 1
    assert ents[0].hasAttr('employeeNumber') and ents[0].getValue('employeeNumber') == description["expected"].encode()
    
def test_ticket49658_23(topo):
    """Do 
        M1: MODRDN    -> V1
        M2: MODRDN    -> V2
        M1: MOD(REPL) -> V1
        M2: MOD(REPL) -> V2
        Replicate:
            M1
            M2
        expected: V2

    :id: 16
    :setup: 3 Master Instances
        1. Use employeenumber=1000,ou=distinguished,ou=people,<suffix>
    :steps:
        1. Isolate M1 and M2 by pausing the replication agreements
        2. On M1 do DEL+ADD 1000 + MOD_ADD_13
        3. On M2 do DEL+ADD 1000 + MOD_ADD_13
        4. Enable replication agreement M2 -> M3, so that update step 2 is replicated first
        5. Enable replication agreement M1 -> M3, so that update step 3 is replicated second
        6. Check that the employeeNumber is 13 on all servers
    :expectedresults:
        1. Fill in the result that is expected
        2. For each test step
    """

    # If you need any test suite initialization,
    # please, write additional fixture for that (including finalizer).
    # Topology for suites are predefined in lib389/topologies.py.

    # If you need host, port or any other data about instance,
    # Please, use the instance object attributes for that (for example, topo.ms["master1"].serverid)
    


    if DEBUGGING:
        # Add debugging steps(if any)...
        pass
    M1 = topo.ms["master1"]
    M2 = topo.ms["master2"]
    M3 = topo.ms["master3"]
    value_init = '7'
    last = '8'
    value_S1 = '8.1'
    value_S2 = '8.2'
    
    description = {
    "S1": M1,
    "S2": M2,
    "S1_MODRDN": value_S1,
    "S1_MOD": [(ldap.MOD_REPLACE, 'employeeNumber', value_S1.encode())],
    "S2_MOD": [(ldap.MOD_REPLACE, 'employeeNumber', value_S2.encode())],
    "S2_MODRDN": value_S2,
    "expected": value_S2}
    
    # This test takes the user_1
    (uid, test_user_dn) = _employeenumber_user_get_dn(int(last))
    
    #
    # Step 4
    #
    # disable all RA from M1 and M2
    # only M3 can replicate the update
    #
    agreement_m1_m2 = M1.agreement.list(suffix=DEFAULT_SUFFIX, consumer_host=M2.host, consumer_port=M2.port)
    agreement_m1_m3 = M1.agreement.list(suffix=DEFAULT_SUFFIX, consumer_host=M3.host, consumer_port=M3.port)
    agreement_m2_m1 = M2.agreement.list(suffix=DEFAULT_SUFFIX, consumer_host=M1.host, consumer_port=M1.port)
    agreement_m2_m3 = M2.agreement.list(suffix=DEFAULT_SUFFIX, consumer_host=M3.host, consumer_port=M3.port)
    
    M1.agreement.pause(agreement_m1_m2[0].dn)
    M1.agreement.pause(agreement_m1_m3[0].dn)
    M2.agreement.pause(agreement_m2_m1[0].dn)
    M2.agreement.pause(agreement_m2_m3[0].dn)

    # Step 5
    # Oldest update
    # check that the entry on M1 contains employeeNumber=<value_end>
    description["S1"].rename_s(test_user_dn, 'employeeNumber=%s' % description["S1_MODRDN"], newsuperior=BASE_DISTINGUISHED, delold=1)
    ents = description["S1"].search_s(BASE_DISTINGUISHED, ldap.SCOPE_SUBTREE, '(employeeNumber=%s)' % description["S1_MODRDN"])
    assert len(ents) == 1
    time.sleep(1)
    
    # Step 6
    # More recent update
    # check that the entry on M2 contains employeeNumber=<value_end>
    description["S2"].rename_s(test_user_dn, 'employeeNumber=%s' % description["S2_MODRDN"], newsuperior=BASE_DISTINGUISHED, delold=1)
    ents = description["S2"].search_s(BASE_DISTINGUISHED, ldap.SCOPE_SUBTREE, '(employeeNumber=%s)' % description["S2_MODRDN"])
    assert len(ents) == 1
    time.sleep(1)

    (no, new_test_user_dn) = _employeenumber_user_get_dn(description["S1_MODRDN"])
    description["S1"].modify_s(new_test_user_dn, description["S1_MOD"])
    ents = description["S1"].search_s(BASE_DISTINGUISHED, ldap.SCOPE_SUBTREE, '(employeeNumber=%s)' % value_S1)
    assert len(ents) == 1
    time.sleep(1)

    (no, new_test_user_dn) = _employeenumber_user_get_dn(description["S2_MODRDN"])
    description["S2"].modify_s(new_test_user_dn, description["S2_MOD"])
    ents = description["S2"].search_s(BASE_DISTINGUISHED, ldap.SCOPE_SUBTREE, '(employeeNumber=%s)' % value_S2)
    assert len(ents) == 1

    #time.sleep(60)
    # Step 7
    # Renable M2 before M1 so that on M3, the most recent update is replicated before
    for ra in agreement_m1_m2, agreement_m1_m3:
        M1.agreement.resume(ra[0].dn)     
        
    # Step 8
    # Renable M1 so that on M3 oldest update is now replicated
    time.sleep(4)
    for ra in agreement_m2_m1, agreement_m2_m3:
        M2.agreement.resume(ra[0].dn)
    
    #time.sleep(3600)
    # Step 9
    # Check that M1 still contains employeeNumber=<value_end>
    ents = M1.search_s(BASE_DISTINGUISHED, ldap.SCOPE_SUBTREE, '(employeeNumber=%s)' % description["expected"])
    log.info('Search M1 employeeNumber=%s (vs. %s)' % (ents[0].getValue('employeeNumber'), description["expected"]))
    assert len(ents) == 1
    assert ents[0].hasAttr('employeeNumber') and ents[0].getValue('employeeNumber') == description["expected"].encode()
        
    # Check that M2 still contains employeeNumber=<value_end>
    ents = M2.search_s(BASE_DISTINGUISHED, ldap.SCOPE_SUBTREE, '(employeeNumber=%s)' % description["expected"])
    log.info('Search M2 employeeNumber=%s (vs. %s)' % (ents[0].getValue('employeeNumber'), description["expected"]))
    assert len(ents) == 1
    assert ents[0].hasAttr('employeeNumber') and ents[0].getValue('employeeNumber') == description["expected"].encode()
    
    # Check that M3 still contain employeeNumber and it contains employeeNumber=<value_end>
    ents = M3.search_s(BASE_DISTINGUISHED, ldap.SCOPE_SUBTREE, '(employeeNumber=*)')
    assert len(ents) == MAX_EMPLOYEENUMBER_USER
    ents = M3.search_s(BASE_DISTINGUISHED, ldap.SCOPE_SUBTREE, '(employeeNumber=%s)' % description["expected"])
    log.info('Search M3 employeeNumber=%s (vs. %s)' % (ents[0].getValue('employeeNumber'), description["expected"]))
    assert len(ents) == 1
    assert ents[0].hasAttr('employeeNumber') and ents[0].getValue('employeeNumber') == description["expected"].encode()
    
def test_ticket49658_24(topo):
    """Do 
        M1: MODRDN    -> V1
        M2: MODRDN    -> V2
        M1: MOD(REPL) -> V1
        M2: MOD(DEL/ADD) -> V2
        Replicate:
            M1
            M2
        expected: V2

    :id: 16
    :setup: 3 Master Instances
        1. Use employeenumber=1000,ou=distinguished,ou=people,<suffix>
    :steps:
        1. Isolate M1 and M2 by pausing the replication agreements
        2. On M1 do DEL+ADD 1000 + MOD_ADD_13
        3. On M2 do DEL+ADD 1000 + MOD_ADD_13
        4. Enable replication agreement M2 -> M3, so that update step 2 is replicated first
        5. Enable replication agreement M1 -> M3, so that update step 3 is replicated second
        6. Check that the employeeNumber is 13 on all servers
    :expectedresults:
        1. Fill in the result that is expected
        2. For each test step
    """

    # If you need any test suite initialization,
    # please, write additional fixture for that (including finalizer).
    # Topology for suites are predefined in lib389/topologies.py.

    # If you need host, port or any other data about instance,
    # Please, use the instance object attributes for that (for example, topo.ms["master1"].serverid)
    


    if DEBUGGING:
        # Add debugging steps(if any)...
        pass
    M1 = topo.ms["master1"]
    M2 = topo.ms["master2"]
    M3 = topo.ms["master3"]
    value_init = '7'
    last = '9'
    value_S1 = '9.1'
    value_S2 = '9.2'
    
    description = {
    "S1": M1,
    "S2": M2,
    "S1_MODRDN": value_S1,
    "S1_MOD": [(ldap.MOD_REPLACE, 'employeeNumber', value_S1.encode())],
    "S2_MOD": [(ldap.MOD_DELETE, 'employeeNumber', value_S2.encode()),(ldap.MOD_ADD, 'employeeNumber', value_S2.encode())],
    "S2_MODRDN": value_S2,
    "expected": value_S2}
    
    # This test takes the user_1
    (uid, test_user_dn) = _employeenumber_user_get_dn(int(last))
    
    #
    # Step 4
    #
    # disable all RA from M1 and M2
    # only M3 can replicate the update
    #
    agreement_m1_m2 = M1.agreement.list(suffix=DEFAULT_SUFFIX, consumer_host=M2.host, consumer_port=M2.port)
    agreement_m1_m3 = M1.agreement.list(suffix=DEFAULT_SUFFIX, consumer_host=M3.host, consumer_port=M3.port)
    agreement_m2_m1 = M2.agreement.list(suffix=DEFAULT_SUFFIX, consumer_host=M1.host, consumer_port=M1.port)
    agreement_m2_m3 = M2.agreement.list(suffix=DEFAULT_SUFFIX, consumer_host=M3.host, consumer_port=M3.port)
    
    M1.agreement.pause(agreement_m1_m2[0].dn)
    M1.agreement.pause(agreement_m1_m3[0].dn)
    M2.agreement.pause(agreement_m2_m1[0].dn)
    M2.agreement.pause(agreement_m2_m3[0].dn)

    # Step 5
    # Oldest update
    # check that the entry on M1 contains employeeNumber=<value_end>
    description["S1"].rename_s(test_user_dn, 'employeeNumber=%s' % description["S1_MODRDN"], newsuperior=BASE_DISTINGUISHED, delold=1)
    ents = description["S1"].search_s(BASE_DISTINGUISHED, ldap.SCOPE_SUBTREE, '(employeeNumber=%s)' % description["S1_MODRDN"])
    assert len(ents) == 1
    time.sleep(1)
    
    # Step 6
    # More recent update
    # check that the entry on M2 contains employeeNumber=<value_end>
    description["S2"].rename_s(test_user_dn, 'employeeNumber=%s' % description["S2_MODRDN"], newsuperior=BASE_DISTINGUISHED, delold=1)
    ents = description["S2"].search_s(BASE_DISTINGUISHED, ldap.SCOPE_SUBTREE, '(employeeNumber=%s)' % description["S2_MODRDN"])
    assert len(ents) == 1
    time.sleep(1)

    (no, new_test_user_dn) = _employeenumber_user_get_dn(description["S1_MODRDN"])
    description["S1"].modify_s(new_test_user_dn, description["S1_MOD"])
    ents = description["S1"].search_s(BASE_DISTINGUISHED, ldap.SCOPE_SUBTREE, '(employeeNumber=%s)' % value_S1)
    assert len(ents) == 1
    time.sleep(1)

    (no, new_test_user_dn) = _employeenumber_user_get_dn(description["S2_MODRDN"])
    description["S2"].modify_s(new_test_user_dn, description["S2_MOD"])
    ents = description["S2"].search_s(BASE_DISTINGUISHED, ldap.SCOPE_SUBTREE, '(employeeNumber=%s)' % value_S2)
    assert len(ents) == 1

    #time.sleep(60)
    # Step 7
    # Renable M2 before M1 so that on M3, the most recent update is replicated before
    for ra in agreement_m1_m2, agreement_m1_m3:
        M1.agreement.resume(ra[0].dn)     
        
    # Step 8
    # Renable M1 so that on M3 oldest update is now replicated
    time.sleep(4)
    for ra in agreement_m2_m1, agreement_m2_m3:
        M2.agreement.resume(ra[0].dn)
    
    #time.sleep(3600)
    # Step 9
    # Check that M1 still contains employeeNumber=<value_end>
    ents = M1.search_s(BASE_DISTINGUISHED, ldap.SCOPE_SUBTREE, '(employeeNumber=%s)' % description["expected"])
    log.info('Search M1 employeeNumber=%s (vs. %s)' % (ents[0].getValue('employeeNumber'), description["expected"]))
    assert len(ents) == 1
    assert ents[0].hasAttr('employeeNumber') and ents[0].getValue('employeeNumber') == description["expected"].encode()
        
    # Check that M2 still contains employeeNumber=<value_end>
    ents = M2.search_s(BASE_DISTINGUISHED, ldap.SCOPE_SUBTREE, '(employeeNumber=%s)' % description["expected"])
    log.info('Search M2 employeeNumber=%s (vs. %s)' % (ents[0].getValue('employeeNumber'), description["expected"]))
    assert len(ents) == 1
    assert ents[0].hasAttr('employeeNumber') and ents[0].getValue('employeeNumber') == description["expected"].encode()
    
    # Check that M3 still contain employeeNumber and it contains employeeNumber=<value_end>
    ents = M3.search_s(BASE_DISTINGUISHED, ldap.SCOPE_SUBTREE, '(employeeNumber=*)')
    assert len(ents) == MAX_EMPLOYEENUMBER_USER
    ents = M3.search_s(BASE_DISTINGUISHED, ldap.SCOPE_SUBTREE, '(employeeNumber=%s)' % description["expected"])
    log.info('Search M3 employeeNumber=%s (vs. %s)' % (ents[0].getValue('employeeNumber'), description["expected"]))
    assert len(ents) == 1
    assert ents[0].hasAttr('employeeNumber') and ents[0].getValue('employeeNumber') == description["expected"].encode()
if __name__ == '__main__':
    # Run isolated
    # -s for DEBUG mode
    CURRENT_FILE = os.path.realpath(__file__)
    pytest.main(["-s", CURRENT_FILE])

