Skip to content

Commit

Permalink
Ticket #48226 - CI test: added test cases for ticket 48226
Browse files Browse the repository at this point in the history
Description: In MMR, double free coould occur under some special condition

This test script was written by thierry bordaz <tbordaz@redhat.com>.
A small modification to check the memory leak was added.

(cherry picked from commit f5d2445)
(cherry picked from commit 8600a5e)
  • Loading branch information
nhosoi committed Jul 16, 2015
1 parent de1b027 commit dfcfa55
Showing 1 changed file with 239 additions and 0 deletions.
239 changes: 239 additions & 0 deletions 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()

0 comments on commit dfcfa55

Please sign in to comment.