From 61c6508543204e10aa105b1a8e940c8c7d604fac Mon Sep 17 00:00:00 2001 From: Timo Tietavainen Date: Sun, 5 Dec 2021 16:13:01 +0200 Subject: [PATCH] Add config and rmr UTs back, fix exception memory free Take configuration and rmr unit tests back into use after fixing the tests. Improve earlier memory leak fix what was done in the version 3.0.0 to free memory also in a case when python exception has been thrown. Issue-Id: RIC-865 Signed-off-by: Timo Tietavainen Change-Id: I2a6708fe3dd10d7fea8b5fb5ead8fd895d6826bd --- docs/release-notes.rst | 5 +++++ ricxappframe/rmr/rmr.py | 2 +- ricxappframe/rmr/rmrclib/rmrclib.py | 19 +++++++++++++++---- setup.py | 2 +- tests/test_config.py | 14 +++++++++----- tests/test_rmr.py | 7 +++++++ tox.ini | 2 +- 7 files changed, 39 insertions(+), 12 deletions(-) diff --git a/docs/release-notes.rst b/docs/release-notes.rst index 13ed41f..2a40b55 100644 --- a/docs/release-notes.rst +++ b/docs/release-notes.rst @@ -10,6 +10,11 @@ All notable changes to this project will be documented in this file. The format is based on `Keep a Changelog `__ and this project adheres to `Semantic Versioning `__. +[3.0.1] - 2021-12-07 +-------------------- +* Take configuration and rmr unit tests back into use after fixing the tests (`RIC-865 `_) +* Improve memory leak fix done in the version 3.0.0 to free memory also if python exception has been thrown. + [3.0.0] - 2021-12-03 -------------------- * Upgrade to RMR version 4.8.0 to fix memory leak in get_constants() function (`RIC-858 `_) diff --git a/ricxappframe/rmr/rmr.py b/ricxappframe/rmr/rmr.py index d9519e5..0e57200 100644 --- a/ricxappframe/rmr/rmr.py +++ b/ricxappframe/rmr/rmr.py @@ -685,7 +685,7 @@ def rmr_wh_call(vctx: c_void_p, whid: c_int, ptr_mbuf: POINTER(rmr_mbuf_t), call return _rmr_wh_call(vctx, whid, ptr_mbuf, call_id, max_wait) -_rmr_wh_close = _wrap_rmr_function('rmr_close', None, [c_void_p, c_int]) +_rmr_wh_close = _wrap_rmr_function('rmr_wh_close', None, [c_void_p, c_int]) def rmr_wh_close(vctx: c_void_p, whid: c_int): diff --git a/ricxappframe/rmr/rmrclib/rmrclib.py b/ricxappframe/rmr/rmrclib/rmrclib.py index 6150e23..953b76f 100644 --- a/ricxappframe/rmr/rmrclib/rmrclib.py +++ b/ricxappframe/rmr/rmrclib/rmrclib.py @@ -16,6 +16,7 @@ # ================================================================================== import ctypes import json +from contextlib import contextmanager # Subpackage that creates and publishes a reference to the C shared library. # Intended to be private; RMR-python and xapp-frame-py users should not need this. @@ -34,6 +35,15 @@ _rmr_free_consts.argtypes = [ctypes.POINTER(ctypes.c_char)] _rmr_free_consts.restype = None +@contextmanager +def _rmr_get_consts_decorator(): + ptr = _rmr_get_consts() + try: + yield ptr + finally: + _rmr_free_consts(ptr) + + def get_constants(cache={}): """ Gets constants published by RMR and caches for subsequent calls. @@ -42,10 +52,11 @@ def get_constants(cache={}): if cache: return cache - ptr = _rmr_get_consts() # read char pointer - js = ctypes.cast(ptr, ctypes.c_char_p).value # cast to json string - cache = json.loads(str(js.decode())) # create constants value object as a hash - _rmr_free_consts(ptr) + # read pointer to json data + with _rmr_get_consts_decorator() as ptr: + js = ctypes.cast(ptr, ctypes.c_char_p).value # cast it to python string + cache = json.loads(str(js.decode())) # create constants value object as a hash + return cache diff --git a/setup.py b/setup.py index 34ccbb1..f3d0576 100644 --- a/setup.py +++ b/setup.py @@ -32,7 +32,7 @@ def _long_descr(): setup( name="ricxappframe", - version="3.0.0", + version="3.0.1", packages=find_packages(exclude=["tests.*", "tests"]), author="O-RAN Software Community", description="Xapp and RMR framework for Python", diff --git a/tests/test_config.py b/tests/test_config.py index e1cbb8f..ce49cdc 100644 --- a/tests/test_config.py +++ b/tests/test_config.py @@ -64,6 +64,7 @@ def test_config_no_env(monkeypatch): time.sleep(3) assert not config_event_seen rmr_xapp_noconfig.stop() + rmr_xapp_noconfig = None def test_default_config_handler(monkeypatch): @@ -83,6 +84,7 @@ def test_default_config_handler(monkeypatch): # give the work loop a chance to timeout on RMR and process the config event time.sleep(3) rmr_xapp_defconfig.stop() + rmr_xapp_defconfig = None def test_custom_config_handler(monkeypatch): @@ -115,6 +117,7 @@ def test_custom_config_handler(monkeypatch): time.sleep(3) assert change_config_event rmr_xapp_config.stop() + rmr_xapp_config = None def teardown_module(): @@ -126,8 +129,9 @@ def teardown_module(): """ os.remove(config_file_path) with suppress(Exception): - rmr_xapp_config.stop() - with suppress(Exception): - rmr_xapp_defconfig.stop() - with suppress(Exception): - rmr_xapp_noconfig.stop() + if rmr_xapp_config: + rmr_xapp_config.stop() + if rmr_xapp_defconfig: + rmr_xapp_defconfig.stop() + if rmr_xapp_noconfig: + rmr_xapp_noconfig.stop() diff --git a/tests/test_rmr.py b/tests/test_rmr.py index 614e839..bd3f4f3 100644 --- a/tests/test_rmr.py +++ b/tests/test_rmr.py @@ -388,6 +388,13 @@ def test_wh(): assert send_summary[rmr.RMR_MS_MSG_TYPE] == rcv_summary[rmr.RMR_MS_MSG_TYPE] == mtype assert send_summary[rmr.RMR_MS_PAYLOAD] == rcv_summary[rmr.RMR_MS_PAYLOAD] == payload + sbuf_send = rmr.rmr_alloc_msg(MRC_SEND, SIZE) + _assert_new_sbuf(sbuf_send) + mtype = 1 + sbuf_send.contents.mtype = mtype + payload = b"Birds like worms" + rmr.set_payload_and_length(payload, sbuf_send) + # send without waiting for a response rmr.rmr_wh_send_msg(MRC_SEND, whid, sbuf_send) diff --git a/tox.ini b/tox.ini index 994391e..0180e50 100644 --- a/tox.ini +++ b/tox.ini @@ -31,7 +31,7 @@ setenv = commands = # add -s flag after pytest to show logs immediately instead of delaying - pytest --ignore=tests/test_config.py --ignore=tests/test_rmr.py --cov ricxappframe --cov-report xml --cov-report term-missing --cov-report html --cov-fail-under=70 --junitxml=/tmp/tests.xml + pytest --cov ricxappframe --cov-report xml --cov-report term-missing --cov-report html --cov-fail-under=70 --junitxml=/tmp/tests.xml coverage xml -i [testenv:flake8] -- 2.16.6