#50847 Issue 49761 - Fix CI test suite issues
Closed 3 years ago by spichugi. Opened 4 years ago by sgouvern.
sgouvern/389-ds-base rhds_58  into  master

@@ -0,0 +1,166 @@ 

+ # --- BEGIN COPYRIGHT BLOCK ---

+ # Copyright (C) 2020 Red Hat, Inc.

+ # All rights reserved.

+ #

+ # License: GPL (version 3 or any later version).

+ # See LICENSE for details.

+ # --- END COPYRIGHT BLOCK ---

+ #

+ import pytest

+ from lib389.replica import Replicas, Replica

+ from lib389.tasks import *

+ from lib389.utils import *

+ from lib389.paths import Paths

+ from lib389.topologies import topology_m2

+ 

+ from lib389._constants import (DEFAULT_SUFFIX, DN_CONFIG)

+ from lib389.properties import (REPLICA_PURGE_DELAY, REPLICA_PURGE_INTERVAL)

+ 

+ from lib389.idm.user import UserAccounts

+ 

+ pytestmark = pytest.mark.tier2

+ 

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

+ 

+ ds_paths = Paths()

+ 

+ @pytest.fixture(scope="module")

+ def topology_setup(topology_m2):

+     """Configure the topology with purge parameters and enable audit logging

+ 

+         - configure replica purge delay and interval on master1 and master2

+         - enable audit log on master1 and master2

+         - restart master1 and master2

+     """

+     m1 = topology_m2.ms["master1"]

+     m2 = topology_m2.ms["master2"]

+ 

+     replica1 = Replicas(m1).get(DEFAULT_SUFFIX)

+     replica2 = Replicas(m2).get(DEFAULT_SUFFIX)

+ 

+     replica1.set('nsDS5ReplicaPurgeDelay','5')

+     replica2.set('nsDS5ReplicaPurgeDelay','5')

+     assert replica1.present('nsDS5ReplicaPurgeDelay')

+     assert replica2.present('nsDS5ReplicaPurgeDelay')

+     replica1.display_attr('nsDS5ReplicaPurgeDelay')

+     replica2.display_attr('nsDS5ReplicaPurgeDelay')

+ 

+     replica1.set('nsDS5ReplicaTombstonePurgeInterval', '5')

+     replica2.set('nsDS5ReplicaTombstonePurgeInterval', '5')

+     assert replica1.present('nsDS5ReplicaTombstonePurgeInterval')

+     assert replica2.present('nsDS5ReplicaTombstonePurgeInterval')

+     replica1.display_attr('nsDS5ReplicaTombstonePurgeInterval')

+     replica2.display_attr('nsDS5ReplicaTombstonePurgeInterval')

+ 

+ 

+     m1.config.set('nsslapd-auditlog-logging-enabled', 'on')

+     m2.config.set('nsslapd-auditlog-logging-enabled', 'on')

+     m1.restart()

+     m2.restart()

+ 

+ 

+ @pytest.mark.skipif(not ds_paths.asan_enabled, reason="Don't run if ASAN is not enabled")

+ @pytest.mark.ds48226

+ @pytest.mark.bz1243970

+ @pytest.mark.bz1262363

+ def test_MMR_double_free(topology_m2, topology_setup, timeout=5):

+     """Reproduce conditions where a double free occurs and check it does not make

+     the server crash

+ 

+     :id: 91580b1c-ad10-49bc-8aed-402edac59f46 

+     :setup: replicated topology - purge delay and purge interval are configured

+     :steps:

+         1. create an entry on master1

+         2. modify the entry with description add

+         3. check the entry is correctly replicated on master2

+         4. stop master2

+         5. delete the entry's description on master1

+         6. stop master1

+         7. start master2

+         8. delete the entry's description on master2

+         9. add an entry's description on master2

+         10. wait the purge delay duration

+         11. add again an entry's description on master2

+     :expectedresults:

+         1. entry exists on master1

+         2. modification is effective 

+         3. entry exists on master2 and modification is effective

+         4. master2 is stopped

+         5. description is removed from entry on master1

+         6. master1 is stopped

+         7. master2 is started - not synchronized with master1

+         8. description is removed from entry on master2 (same op should be performed too by replication mecanism)

+         9. description to entry is added on master2

+         10. Purge delay has expired - changes are erased 

+         11.  description to entry is added again on master2

+     """

+     name = 'test_entry'

+ 

+     entry_m1 = UserAccounts(topology_m2.ms["master1"], DEFAULT_SUFFIX)

+     entry = entry_m1.create(properties={

+         'uid': name,

+         'sn': name,

+         'cn': name,

+         'uidNumber': '1001',

+         'gidNumber': '1001',

+         'homeDirectory': '/home/test_entry',

+         'userPassword': 'test_entry_pwd'

+     })

+ 

+     log.info('First do an update that is replicated')

+     entry.add('description', '5')

+ 

+     log.info('Check the update in the replicated entry')

+     entry_m2 = UserAccounts(topology_m2.ms["master2"], DEFAULT_SUFFIX)

+ 

+     success = 0

+     for i in range(0, timeout):

+         try:

+             entry_repl = entry_m2.get(name)

+             out = entry_repl.display_attr('description')

+             if len(out) > 0:

+                 success = 1

+                 break

+         except:

+             time.sleep(1)

+ 

+     assert success

+ 

+     log.info('Stop M2 so that it will not receive the next update')

+     topology_m2.ms["master2"].stop(10)

+ 

+     log.info('Perform a del operation that is not replicated')

+     entry.remove('description', '5')

+ 

+     log.info("Stop M1 so that it will keep del '5' that is unknown from master2")

+     topology_m2.ms["master1"].stop(10)

+ 

+     log.info('start M2 to do the next updates')

+     topology_m2.ms["master2"].start()

+ 

+     log.info("del 'description' by '5'")

+     entry_repl.remove('description', '5')

+ 

+     log.info("add 'description' by '5'")

+     entry_repl.add('description', '5')

+ 

+     log.info('sleep of purge delay so that the next update will purge the CSN_7')

+     time.sleep(6)

+ 

+     log.info("add 'description' by '6' that purge the state info")

+     entry_repl.add('description', '6')

+      

+     log.info('Restart master1')

+     topology_m2.ms["master1"].start(30)

+ 

+ 

+ if __name__ == '__main__':

+     # Run isolated

+     # -s for DEBUG mode

+     CURRENT_FILE = os.path.realpath(__file__)

+     pytest.main("-s %s" % CURRENT_FILE)

@@ -1,141 +0,0 @@ 

- # --- BEGIN COPYRIGHT BLOCK ---

- # Copyright (C) 2016 Red Hat, Inc.

- # All rights reserved.

- #

- # License: GPL (version 3 or any later version).

- # See LICENSE for details.

- # --- END COPYRIGHT BLOCK ---

- #

- import pytest

- from lib389.tasks import *

- from lib389.utils import *

- from lib389.topologies import topology_m2

- 

- from lib389._constants import (DEFAULT_SUFFIX, REPLICA_PURGE_DELAY, REPLICA_PURGE_INTERVAL, DN_CONFIG,

-                               SUFFIX, VALGRIND_LEAK_STR, VALGRIND_INVALID_STR)

- 

- pytestmark = pytest.mark.tier2

- 

- logging.getLogger(__name__).setLevel(logging.DEBUG)

- log = logging.getLogger(__name__)

- 

- 

- def test_ticket48226_set_purgedelay(topology_m2):

-     args = {REPLICA_PURGE_DELAY: '5',

-             REPLICA_PURGE_INTERVAL: '5'}

-     try:

-         topology_m2.ms["master1"].replica.setProperties(DEFAULT_SUFFIX, None, None, args)

-     except:

-         log.fatal('Failed to configure replica')

-         assert False

-     try:

-         topology_m2.ms["master2"].replica.setProperties(DEFAULT_SUFFIX, None, None, args)

-     except:

-         log.fatal('Failed to configure replica')

-         assert False

-     topology_m2.ms["master1"].modify_s(DN_CONFIG, [(ldap.MOD_REPLACE, 'nsslapd-auditlog-logging-enabled', 'on')])

-     topology_m2.ms["master2"].modify_s(DN_CONFIG, [(ldap.MOD_REPLACE, 'nsslapd-auditlog-logging-enabled', 'on')])

-     topology_m2.ms["master1"].restart()

-     topology_m2.ms["master2"].restart()

- 

- 

- def test_ticket48226_1(topology_m2):

-     name = 'test_entry'

-     dn = "cn=%s,%s" % (name, SUFFIX)

- 

-     topology_m2.ms["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_m2.ms["master1"].modify_s(dn, mods)

- 

-     nbtry = 0

-     while (nbtry <= 10):

-         try:

-             ent = topology_m2.ms["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_m2.ms["master2"].stop(10)

- 

-     # ADD a new value that is not replicated

-     mods = [(ldap.MOD_DELETE, 'description', '5')]

-     topology_m2.ms["master1"].modify_s(dn, mods)

- 

-     # Stop M1 so that it will keep del '5' that is unknown from master2

-     topology_m2.ms["master1"].stop(10)

- 

-     # Get the sbin directory so we know where to replace 'ns-slapd'

-     sbin_dir = topology_m2.ms["master2"].get_sbin_dir()

- 

-     # Wrap valgrind in the try-finally block to make sure it is teared down

-     try:

-         if not topology_m2.ms["master2"].has_asan():

-             valgrind_enable(sbin_dir)

- 

-         # start M2 to do the next updates

-         topology_m2.ms["master2"].start()

- 

-         # ADD 'description' by '5'

-         mods = [(ldap.MOD_DELETE, 'description', '5')]

-         topology_m2.ms["master2"].modify_s(dn, mods)

- 

-         # DEL 'description' by '5'

-         mods = [(ldap.MOD_ADD, 'description', '5')]

-         topology_m2.ms["master2"].modify_s(dn, mods)

- 

-         # sleep of purge delay so that the next update will purge the CSN_7

-         time.sleep(6)

- 

-         # ADD 'description' by '6' that purge the state info

-         mods = [(ldap.MOD_ADD, 'description', '6')]

-         topology_m2.ms["master2"].modify_s(dn, mods)

- 

-         # Restart master1

-         # topology_m2.ms["master1"].start(30)

- 

-         if not topology_m2.ms["master2"].has_asan():

-             results_file = valgrind_get_results_file(topology_m2.ms["master2"])

- 

-         # Stop master2

-         topology_m2.ms["master2"].stop(30)

- 

-         # Check for leak

-         if not topology_m2.ms["master2"].has_asan():

-             if valgrind_check_file(results_file, VALGRIND_LEAK_STR, 'csnset_dup'):

-                 log.info('Valgrind reported leak in csnset_dup!')

-                 assert False

-             else:

-                 log.info('Valgrind is happy!')

- 

-             # Check for invalid read/write

-             if valgrind_check_file(results_file, VALGRIND_INVALID_STR, 'csnset_dup'):

-                 log.info('Valgrind reported invalid!')

-                 assert False

-             else:

-                 log.info('Valgrind is happy!')

- 

-             # Check for invalid read/write

-             if valgrind_check_file(results_file, VALGRIND_INVALID_STR, 'csnset_free'):

-                 log.info('Valgrind reported invalid!')

-                 assert False

-             else:

-                 log.info('Valgrind is happy!')

-     finally:

-         if not topology_m2.ms["master2"].has_asan():

-             valgrind_disable(sbin_dir)

- 

- 

- if __name__ == '__main__':

-     # Run isolated

-     # -s for DEBUG mode

-     CURRENT_FILE = os.path.realpath(__file__)

-     pytest.main("-s %s" % CURRENT_FILE)

Bug Description:
tickets/ticket48229 test had failures in CI nightly runs

Fix Description:
tickets/ticket48226_test.py file moved and renamed to tests/suite/memory_leaks/MMR_double_free_test.py
Use of Valgrind removed, as support for Valgrind is broken in lib389 - Test run only with ASAN build
Replaced depracated _s functions by use of DSLdapObject

Relates https://pagure.io/389-ds-base/issue/49761

Author: sgouvern

Review by: vashirov, spichugi

This should be a pytest fixture instead of a standalone test.

Please also run git rm -f dirsrvtests/tests/tickets/ticket48226_test.py to remove the old ticket.

And we should use Replica(DSLdapObject) or direct search_s. Legacy Replica will be deprecated soon

Alternatively, you can change the comments to log.info calls. It will be nice, I think :)

Small nitpick, please, change the function name to something meaningful. We already have the Issue name in the pytest.mark

rebased onto 42f7e5f8bfa39e62f350524ca2c3ac7515cfc1cd

4 years ago

Thanks for your reviews.
I updated the PR taking your remarks into account.

LGTM!
Please fix up commits and rebase to master.

rebased onto e48172d9c05d14e8ab8f8ae02a4ba44a9f19b2fa

4 years ago

rebased onto bf8b4af

4 years ago

Pull-Request has been merged by vashirov

4 years ago

389-ds-base is moving from Pagure to Github. This means that new issues and pull requests
will be accepted only in 389-ds-base's github repository.

This pull request has been cloned to Github as issue and is available here:
- https://github.com/389ds/389-ds-base/issues/3901

If you want to continue to work on the PR, please navigate to the github issue,
download the patch from the attachments and file a new pull request.

Thank you for understanding. We apologize for all inconvenience.

Pull-Request has been closed by spichugi

3 years ago