From e6b20ffcc995b2ac190b96850073c0569bc6d294 Mon Sep 17 00:00:00 2001 From: Noriko Hosoi Date: Thu, 16 Jul 2015 10:41:53 -0700 Subject: [PATCH 25/30] Ticket #48226 - CI test: added test cases for ticket 48226 Description: In MMR, double free coould occur under some special condition This test script was written by thierry bordaz . A small modification to check the memory leak was added. (cherry picked from commit f5d24450477f8341261c3e5cb5c54ec1ab83328f) (cherry picked from commit 8600a5eabc78848ad1bf0a9c2014823d0cd6cedc) --- dirsrvtests/tickets/ticket48226_test.py | 239 ++++++++++++++++++++++++++++++++ 1 file changed, 239 insertions(+) create mode 100644 dirsrvtests/tickets/ticket48226_test.py diff --git a/dirsrvtests/tickets/ticket48226_test.py b/dirsrvtests/tickets/ticket48226_test.py new file mode 100644 index 0000000..87814e7 --- /dev/null +++ b/dirsrvtests/tickets/ticket48226_test.py @@ -0,0 +1,239 @@ +# --- BEGIN COPYRIGHT BLOCK --- +# Copyright (C) 2015 Red Hat, Inc. +# All rights reserved. +# +# License: GPL (version 3 or any later version). +# See LICENSE for details. +# --- END COPYRIGHT BLOCK --- +# +import os +import sys +import time +import ldap +import logging +import pytest +from lib389 import DirSrv, Entry, tools, tasks +from lib389.tools import DirSrvTools +from lib389._constants import * +from lib389.properties import * +from lib389.tasks import * +from lib389.utils import * + +logging.getLogger(__name__).setLevel(logging.DEBUG) +log = logging.getLogger(__name__) + +installation1_prefix = None + + +class TopologyReplication(object): + def __init__(self, master1, master2): + master1.open() + self.master1 = master1 + master2.open() + self.master2 = master2 + + +@pytest.fixture(scope="module") +def topology(request): + global installation1_prefix + os.environ['USE_VALGRIND'] = '1' + if installation1_prefix: + args_instance[SER_DEPLOYED_DIR] = installation1_prefix + + # Creating master 1... + master1 = DirSrv(verbose=False) + if installation1_prefix: + args_instance[SER_DEPLOYED_DIR] = installation1_prefix + args_instance[SER_HOST] = HOST_MASTER_1 + args_instance[SER_PORT] = PORT_MASTER_1 + args_instance[SER_SERVERID_PROP] = SERVERID_MASTER_1 + args_instance[SER_CREATION_SUFFIX] = DEFAULT_SUFFIX + args_master = args_instance.copy() + master1.allocate(args_master) + instance_master1 = master1.exists() + if instance_master1: + master1.delete() + master1.create() + master1.open() + master1.replica.enableReplication(suffix=SUFFIX, role=REPLICAROLE_MASTER, replicaId=REPLICAID_MASTER_1) + + # Creating master 2... + master2 = DirSrv(verbose=False) + if installation1_prefix: + args_instance[SER_DEPLOYED_DIR] = installation1_prefix + args_instance[SER_HOST] = HOST_MASTER_2 + args_instance[SER_PORT] = PORT_MASTER_2 + args_instance[SER_SERVERID_PROP] = SERVERID_MASTER_2 + args_instance[SER_CREATION_SUFFIX] = DEFAULT_SUFFIX + args_master = args_instance.copy() + master2.allocate(args_master) + instance_master2 = master2.exists() + if instance_master2: + master2.delete() + master2.create() + master2.open() + master2.replica.enableReplication(suffix=SUFFIX, role=REPLICAROLE_MASTER, replicaId=REPLICAID_MASTER_2) + + # + # Create all the agreements + # + # Creating agreement from master 1 to master 2 + properties = {RA_NAME: r'meTo_$host:$port', + RA_BINDDN: defaultProperties[REPLICATION_BIND_DN], + RA_BINDPW: defaultProperties[REPLICATION_BIND_PW], + RA_METHOD: defaultProperties[REPLICATION_BIND_METHOD], + RA_TRANSPORT_PROT: defaultProperties[REPLICATION_TRANSPORT]} + m1_m2_agmt = master1.agreement.create(suffix=SUFFIX, host=master2.host, port=master2.port, properties=properties) + if not m1_m2_agmt: + log.fatal("Fail to create a master -> master replica agreement") + sys.exit(1) + log.debug("%s created" % m1_m2_agmt) + + # Creating agreement from master 2 to master 1 + properties = {RA_NAME: r'meTo_$host:$port', + RA_BINDDN: defaultProperties[REPLICATION_BIND_DN], + RA_BINDPW: defaultProperties[REPLICATION_BIND_PW], + RA_METHOD: defaultProperties[REPLICATION_BIND_METHOD], + RA_TRANSPORT_PROT: defaultProperties[REPLICATION_TRANSPORT]} + m2_m1_agmt = master2.agreement.create(suffix=SUFFIX, host=master1.host, port=master1.port, properties=properties) + if not m2_m1_agmt: + log.fatal("Fail to create a master -> master replica agreement") + sys.exit(1) + log.debug("%s created" % m2_m1_agmt) + + # Allow the replicas to get situated with the new agreements... + time.sleep(5) + + # + # Initialize all the agreements + # + master1.agreement.init(SUFFIX, HOST_MASTER_2, PORT_MASTER_2) + master1.waitForReplInit(m1_m2_agmt) + + # Check replication is working... + if master1.testReplication(DEFAULT_SUFFIX, master2): + log.info('Replication is working.') + else: + log.fatal('Replication is not working.') + assert False + + # Clear out the tmp dir + master1.clearTmpDir(__file__) + + return TopologyReplication(master1, master2) + +def test_ticket11111_set_purgedelay(topology): + args = {REPLICA_PURGE_DELAY: '5', + REPLICA_PURGE_INTERVAL: '5'} + try: + topology.master1.replica.setProperties(DEFAULT_SUFFIX, None, None, args) + except: + log.fatal('Failed to configure replica') + assert False + try: + topology.master2.replica.setProperties(DEFAULT_SUFFIX, None, None, args) + except: + log.fatal('Failed to configure replica') + assert False + topology.master1.modify_s(DN_CONFIG, [(ldap.MOD_REPLACE, 'nsslapd-auditlog-logging-enabled', 'on')]) + topology.master2.modify_s(DN_CONFIG, [(ldap.MOD_REPLACE, 'nsslapd-auditlog-logging-enabled', 'on')]) + topology.master1.restart(10) + topology.master2.restart(10) + + +def test_ticket11111_1(topology): + name = 'test_entry' + dn = "cn=%s,%s" % (name, SUFFIX) + + topology.master1.add_s(Entry((dn , { + 'objectclass': "top person".split(), + 'sn': name, + 'cn': name}))) + + # First do an update that is replicated + mods = [(ldap.MOD_ADD, 'description', '5')] + topology.master1.modify_s(dn, mods) + + nbtry = 0 + while (nbtry <= 10): + try: + ent = topology.master2.getEntry(dn, ldap.SCOPE_BASE, "(objectclass=*)", ['description']) + if ent.hasAttr('description') and ent.getValue('description') == '5': + break + except ldap.NO_SUCH_OBJECT: + pass + nbtry = nbtry + 1 + time.sleep(1) + assert nbtry <= 10 + + # Stop M2 so that it will not receive the next update + topology.master2.stop(10) + + # ADD a new value that is not replicated + mods = [(ldap.MOD_DELETE, 'description', '5')] + topology.master1.modify_s(dn, mods) + + # Stop M1 so that it will keep del '5' that is unknown from master2 + topology.master1.stop(10) + + # Get the sbin directory so we know where to replace 'ns-slapd' + sbin_dir = get_sbin_dir(prefix=topology.master2.prefix) + + # Enable valgrind + valgrind_enable(sbin_dir) + + # start M2 to do the next updates + topology.master2.start(10) + + # ADD 'description' by '5' + mods = [(ldap.MOD_DELETE, 'description', '5')] + topology.master2.modify_s(dn, mods) + + # DEL 'description' by '5' + mods = [(ldap.MOD_ADD, 'description', '5')] + topology.master2.modify_s(dn, mods) + + # sleep of purgedelay so that the next update will purge the CSN_7 + time.sleep(6) + + # ADD 'description' by '8' that purge the state info + mods = [(ldap.MOD_ADD, 'description', '6')] + topology.master2.modify_s(dn, mods) + + if valgrind_check_leak(topology.master2, 'csnset_dup'): + log.error('test_csnset_dup: Memory leak is present!') + else: + log.info('test_csnset_dup: No leak is present!') + + if valgrind_check_leak(topology.master2, 'Invalid'): + log.info('Valgrind reported invalid!') + else: + log.info('Valgrind is happy!') + + #log.info("You can attach yourself") + #time.sleep(60) + + # Enable valgrind + valgrind_disable(sbin_dir) + + topology.master1.start(10) + + +def test_ticket11111_final(topology): + topology.master1.delete() + topology.master2.delete() + log.info('Testcase PASSED') + + +def run_isolated(): + global installation1_prefix + installation1_prefix = None + + topo = topology(True) + test_ticket11111_set_purgedelay(topo) + test_ticket11111_1(topo) + + +if __name__ == '__main__': + run_isolated() + -- 1.9.3