Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
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 <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
Showing
1 changed file
with
239 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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() | ||
|