From 6788364c91eb834f4a29b99373ea36c0a975242e Mon Sep 17 00:00:00 2001 From: Tommy Carpenter Date: Wed, 8 Apr 2020 12:40:22 -0400 Subject: [PATCH] RMR Python has been moved to xapp frame. Issue-ID: RIC-228 Change-Id: I527179f3cd9c717789d4d1289728a15597af98aa Signed-off-by: Tommy Carpenter --- CHANGES_WRAPPER.txt | 3 + README | 54 +- src/bindings/rmr-python/Dockerfile-DocGen | 36 -- src/bindings/rmr-python/LICENSE.txt | 29 - src/bindings/rmr-python/README.rst | 17 - src/bindings/rmr-python/docs/Makefile | 20 - src/bindings/rmr-python/docs/make.bat | 35 -- src/bindings/rmr-python/docs/release-notes.rst | 345 ------------ src/bindings/rmr-python/docs/source/conf.py | 56 -- src/bindings/rmr-python/docs/source/index.rst | 104 ---- src/bindings/rmr-python/docs/source/module_api.rst | 16 - src/bindings/rmr-python/examples/README.md | 8 - src/bindings/rmr-python/examples/local.rt | 6 - src/bindings/rmr-python/examples/rcv_all.py | 70 --- src/bindings/rmr-python/examples/receive.py | 56 -- src/bindings/rmr-python/examples/send.py | 64 --- src/bindings/rmr-python/rmr-version.yaml | 3 - src/bindings/rmr-python/rmr/__init__.py | 16 - src/bindings/rmr-python/rmr/exceptions.py | 31 -- src/bindings/rmr-python/rmr/helpers.py | 102 ---- src/bindings/rmr-python/rmr/rmr.py | 593 --------------------- src/bindings/rmr-python/rmr/rmr_mocks/__init__.py | 0 src/bindings/rmr-python/rmr/rmr_mocks/rmr_mocks.py | 156 ------ src/bindings/rmr-python/setup.py | 56 -- src/bindings/rmr-python/tests/conftest.py | 78 --- .../rmr-python/tests/fixtures/test_local.rt | 8 - src/bindings/rmr-python/tests/test_rmr.py | 373 ------------- src/bindings/rmr-python/tests/test_rmr_mocks.py | 114 ---- src/bindings/rmr-python/tox.ini | 42 -- 29 files changed, 30 insertions(+), 2461 deletions(-) delete mode 100644 src/bindings/rmr-python/Dockerfile-DocGen delete mode 100644 src/bindings/rmr-python/LICENSE.txt delete mode 100644 src/bindings/rmr-python/README.rst delete mode 100644 src/bindings/rmr-python/docs/Makefile delete mode 100644 src/bindings/rmr-python/docs/make.bat delete mode 100644 src/bindings/rmr-python/docs/release-notes.rst delete mode 100644 src/bindings/rmr-python/docs/source/conf.py delete mode 100644 src/bindings/rmr-python/docs/source/index.rst delete mode 100644 src/bindings/rmr-python/docs/source/module_api.rst delete mode 100644 src/bindings/rmr-python/examples/README.md delete mode 100644 src/bindings/rmr-python/examples/local.rt delete mode 100644 src/bindings/rmr-python/examples/rcv_all.py delete mode 100644 src/bindings/rmr-python/examples/receive.py delete mode 100644 src/bindings/rmr-python/examples/send.py delete mode 100644 src/bindings/rmr-python/rmr-version.yaml delete mode 100644 src/bindings/rmr-python/rmr/__init__.py delete mode 100644 src/bindings/rmr-python/rmr/exceptions.py delete mode 100644 src/bindings/rmr-python/rmr/helpers.py delete mode 100644 src/bindings/rmr-python/rmr/rmr.py delete mode 100644 src/bindings/rmr-python/rmr/rmr_mocks/__init__.py delete mode 100644 src/bindings/rmr-python/rmr/rmr_mocks/rmr_mocks.py delete mode 100644 src/bindings/rmr-python/setup.py delete mode 100644 src/bindings/rmr-python/tests/conftest.py delete mode 100644 src/bindings/rmr-python/tests/fixtures/test_local.rt delete mode 100644 src/bindings/rmr-python/tests/test_rmr.py delete mode 100644 src/bindings/rmr-python/tests/test_rmr_mocks.py delete mode 100644 src/bindings/rmr-python/tox.ini diff --git a/CHANGES_WRAPPER.txt b/CHANGES_WRAPPER.txt index 1602ab9..d82661c 100644 --- a/CHANGES_WRAPPER.txt +++ b/CHANGES_WRAPPER.txt @@ -5,6 +5,9 @@ #API and build change and fix summaries. Doc correctsions #and/or changes are not mentioned here; see the commit messages. +2020 April 8; Version n/a + RMR Python moved to Python Xapp Framework (https://gerrit.o-ran-sc.org/r/admin/repos/ric-plt/xapp-frame-py) + 2020 February 29; Version 2.4.0 Add consolidated testing under CMake Add support binary for health check (SI95 only) diff --git a/README b/README index bbb5d18..247db4d 100644 --- a/README +++ b/README @@ -1,7 +1,7 @@ # #================================================================================== -# Copyright (c) 2019 Nokia -# Copyright (c) 2018-2019 AT&T Intellectual Property. +# Copyright (c) 2020 Nokia +# Copyright (c) 2018-2020 AT&T Intellectual Property. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. @@ -25,39 +25,39 @@ by the message type and subscription ID, or just the message type. RMR is responsible for establishing and managing each connection freeing the application from any network connectivity management. -This repo contains the source and documentation for both the core RMR library -and for the Python bindings which allow a Python (v3) application to use RMR -to send and receive messages. +This repo contains the source and documentation for the core RMR library. +RMR python bindings are available as a submodule in the xapp-frame-py PyPI package at +https://pypi.org/project/ricxappframe/ and documented at https://docs.o-ran-sc.org/projects/o-ran-sc-ric-plt-xapp-frame-py/en/latest/. The directories at the root level are as follows, each contains its own readme file where additional details are necessary. -ci This directory contains the continuous integration scripts needed - to build and verify RMR when changes are made and committed to the repo. +ci This directory contains the continuous integration scripts needed + to build and verify RMR when changes are made and committed to the repo. -doc RMR documentation is written in a document language and thus is - source code. This directory contains the source for all generated - documentation. +doc RMR documentation is written in a document language and thus is + source code. This directory contains the source for all generated + documentation. -docs This is a 'canned' directory which is intended to be scraped. Direct - editing of documentation files in this directory is dangerous as - most of the files, even though checked into the repo per mandate, - are artifacts and will be overlaid if hand edited. +docs This is a 'canned' directory which is intended to be scraped. Direct + editing of documentation files in this directory is dangerous as + most of the files, even though checked into the repo per mandate, + are artifacts and will be overlaid if hand edited. examples This directory contains example programmes which illustrate the use - of RMR. + of RMR. -ext RMR makes use of NNG (next generation Nanomsg). The ext directory is - the git reference allowing the NNG code to be pulled and built as - a reference. +ext RMR makes use of NNG (next generation Nanomsg). The ext directory is + the git reference allowing the NNG code to be pulled and built as + a reference. -src This directory is the top level source directory containing both the - core RMR code, and any bindings which have been written. +src This directory is the top level source directory containing the + core RMR code. -test All unit and application level tests for the core library are kept - within this directory. Tests for bindings are managed within the - binding's directory under the source directory. +test All unit and application level tests for the core library are kept + within this directory. Tests for bindings are managed within the + binding's directory under the source directory. Top level pollution There are several "configuration" files which sit at the top level of the @@ -66,9 +66,9 @@ if not all of the CI/CD goo is in the ci directory where it's out of the way and thus not confusing. However, there is some pollution that can generally be ignored: - tox.ini -- this seems to drive the scraper which pulls from docs and - writes to some external documentation repo/host. + tox.ini -- this seems to drive the scraper which pulls from docs and + writes to some external documentation repo/host. - .readthedocs.yaml -- this seems to be some configuration for the docs - scraping process(es). + .readthedocs.yaml -- this seems to be some configuration for the docs + scraping process(es). diff --git a/src/bindings/rmr-python/Dockerfile-DocGen b/src/bindings/rmr-python/Dockerfile-DocGen deleted file mode 100644 index 45bb63a..0000000 --- a/src/bindings/rmr-python/Dockerfile-DocGen +++ /dev/null @@ -1,36 +0,0 @@ -# ================================================================================== -# Copyright (c) 2019 Nokia -# Copyright (c) 2018-2019 AT&T Intellectual Property. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. -# ================================================================================== -FROM python:3.7-alpine - -# copy NNG and rmr out of the CI builder nng -# NOTE: rmr-pythons documentation does not change based on what version of rmr is installed, only based on what version rmr-python was built (coding wise) against last, so it doesn't matter if the rmr in the parent repo here is ahead -COPY --from=nexus3.o-ran-sc.org:10004/bldr-alpine3:3-a3.9 /usr/local/lib64/libnng.so /usr/local/lib64/libnng.so -COPY --from=nexus3.o-ran-sc.org:10004/bldr-alpine3:3-a3.9 /usr/local/lib64/librmr_nng.so /usr/local/lib64/librmr_nng.so - -COPY rmr/ /tmp/rmr -COPY docs/ /tmp/docs -WORKDIR /tmp - -# need make for sphinx -RUN apk add --update make - -RUN pip install sphinx numpydoc - -WORKDIR /tmp/docs/ -ENV LD_LIBRARY_PATH /usr/local/lib/:/usr/local/lib64 -# text generates the documentation in text format -CMD make text diff --git a/src/bindings/rmr-python/LICENSE.txt b/src/bindings/rmr-python/LICENSE.txt deleted file mode 100644 index e723ccb..0000000 --- a/src/bindings/rmr-python/LICENSE.txt +++ /dev/null @@ -1,29 +0,0 @@ - - Unless otherwise specified, all software contained herein is licensed - under the Apache License, Version 2.0 (the "Software License"); - you may not use this software except in compliance with the Software - License. You may obtain a copy of the Software License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the Software License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the Software License for the specific language governing permissions - and limitations under the Software License. - - - - Unless otherwise specified, all documentation contained herein is licensed - under the Creative Commons License, Attribution 4.0 Intl. (the - "Documentation License"); you may not use this documentation except in - compliance with the Documentation License. You may obtain a copy of the - Documentation License at - - https://creativecommons.org/licenses/by/4.0/ - - Unless required by applicable law or agreed to in writing, documentation - distributed under the Documentation License is distributed on an "AS IS" - BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or - implied. See the Documentation License for the specific language governing - permissions and limitations under the Documentation License. diff --git a/src/bindings/rmr-python/README.rst b/src/bindings/rmr-python/README.rst deleted file mode 100644 index 2f2201d..0000000 --- a/src/bindings/rmr-python/README.rst +++ /dev/null @@ -1,17 +0,0 @@ -rmr-python -=========== - -Please see `docs/source/index.rst` - -Generating Documentation -======================== - -To generate `rmr-python` documentation: - -:: - - # from the root of rmr-python, not here - docker build -t rmrpythondocs:latest -f Dockerfile-DocGen . - docker run -v ~/desired/target/dir/:/tmp/docs/build/text rmrpythondocs:latest - -After running this, `/desired/target/dir/` will contain `index.rst` and `module_api.txt` diff --git a/src/bindings/rmr-python/docs/Makefile b/src/bindings/rmr-python/docs/Makefile deleted file mode 100644 index d0c3cbf..0000000 --- a/src/bindings/rmr-python/docs/Makefile +++ /dev/null @@ -1,20 +0,0 @@ -# Minimal makefile for Sphinx documentation -# - -# You can set these variables from the command line, and also -# from the environment for the first two. -SPHINXOPTS ?= -SPHINXBUILD ?= sphinx-build -SOURCEDIR = source -BUILDDIR = build - -# Put it first so that "make" without argument is like "make help". -help: - @$(SPHINXBUILD) -M help "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O) - -.PHONY: help Makefile - -# Catch-all target: route all unknown targets to Sphinx using the new -# "make mode" option. $(O) is meant as a shortcut for $(SPHINXOPTS). -%: Makefile - @$(SPHINXBUILD) -M $@ "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O) diff --git a/src/bindings/rmr-python/docs/make.bat b/src/bindings/rmr-python/docs/make.bat deleted file mode 100644 index 6247f7e..0000000 --- a/src/bindings/rmr-python/docs/make.bat +++ /dev/null @@ -1,35 +0,0 @@ -@ECHO OFF - -pushd %~dp0 - -REM Command file for Sphinx documentation - -if "%SPHINXBUILD%" == "" ( - set SPHINXBUILD=sphinx-build -) -set SOURCEDIR=source -set BUILDDIR=build - -if "%1" == "" goto help - -%SPHINXBUILD% >NUL 2>NUL -if errorlevel 9009 ( - echo. - echo.The 'sphinx-build' command was not found. Make sure you have Sphinx - echo.installed, then set the SPHINXBUILD environment variable to point - echo.to the full path of the 'sphinx-build' executable. Alternatively you - echo.may add the Sphinx directory to PATH. - echo. - echo.If you don't have Sphinx installed, grab it from - echo.http://sphinx-doc.org/ - exit /b 1 -) - -%SPHINXBUILD% -M %1 %SOURCEDIR% %BUILDDIR% %SPHINXOPTS% %O% -goto end - -:help -%SPHINXBUILD% -M help %SOURCEDIR% %BUILDDIR% %SPHINXOPTS% %O% - -:end -popd diff --git a/src/bindings/rmr-python/docs/release-notes.rst b/src/bindings/rmr-python/docs/release-notes.rst deleted file mode 100644 index 7017d44..0000000 --- a/src/bindings/rmr-python/docs/release-notes.rst +++ /dev/null @@ -1,345 +0,0 @@ -Change Log -========== - -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 `__. - -[4.0.0] - 3/18/2020 -------------------- - -:: - - * Switch to SI95 instead of NNG. This is a breaking change. SI95 rmr users cannot talk to NNG rmr users. - * The version bump from 2 to 4 is due to the "roommate" issue in the rmr repo. - - -[2.2.1] - 3/3/2020 --------------------- - -:: - - * Correct the MEID unit test (broken by RMR commit 190665fe) - * Change rmr_init to catch init failure reported by RMR - - -[2.2.0] - 12/5/2019 --------------------- - -:: - - * add ability to set a deterministic transaction id in alloc, and in the mock of alloc - * add ability to set meid in fake alloc; before None was always returned erroneously - * Fix a bug where fake_alloc was way out of date with alloc, and add a test for it - - -[2.1.0] - 12/4/2019 --------------------- - -:: - - * Allow the setting of payload and message type in rts - * Add a new function, helpers.rmr_rcvall_msgs_raw, that also returns the sbuf alongside the summary - * Add a mock for free_msg - - -[2.0.0] - 12/2/2019 --------------------- - -:: - * This is a breaking change as it rquires that RMR version 1.10.2 or later be used. - * The populate and set length function will reallocate the message buffer payload if the caller attempts to insert more bytes than the currrent message supports. - * add ability to set subscription id when allocating a message - * add testing involving subscription ids - - -[1.0.0] - 10/24/2019 --------------------- - -:: - - * It's been past due to bump this to 1.0.0 since people depend on it! - * Add the ability to set sbuf attributes in the same call that it is allocated - * (breaking) removes bytes2meid - * (breaking) rmr_set_meid now infers length - * (breaking) rmr_get_meid now returns bytes, to be symmetric with set_meid - - -[0.13.5] - 10/23/2019 --------------------- - -:: - - * Add an exceptions module and raise a proper exception when an allocated buffer has a NULL pointer. Likely due to a bad rmr context. - -[0.13.4] - 10/21/2019 --------------------- - -:: - - * Correct cause of nil pointer exception in message summary. - - -[0.13.3] - 10/10/2019 --------------------- - -:: - - * Add missing unit test for receive all. - * Correct bug in summary function. - -[0.13.2] - 10/2/2019 --------------------- - -:: - - * Fix a constant name (RMRFL_MT_CALL) - -[0.13.1] - 10/1/2019 --------------------- - -:: - - * Correct unit test bug in rmr-python. With RMR 1.8.x connections are forced to be asynch by default to prevent kubernetes blocking the attempt for minutes. However, the asynch nature of connections makes unit tests concerned with the ability to send and receive messages non-deterministic as some connections are established before the first message is sent, and others are not. This change ensures that unit tests establish connections in a synchronous manner which ensures that the first send will not be rejected by NNG due to a pending connection. - -[0.13.0] - 9/27/2019 --------------------- - -:: - * Add a helpers module to provide extensions and helper functions such as receive all queued messages. - * Enhance unit test to check only for RMR constants which are needed. - * Correct unprintable characters in documentation. - - -[0.12.0] - 8/23/2019 --------------------- - -:: - * Add final unit tests for rmr.py; unit test coverage for rmr python is about 95%. The remaining functions are dangerous to unit test directly, e.g., rcv which may block forever - * Fix a bug where meid was being intepreted as bytes (but then cast into a string); the correct interpretation is a string, so now it will truncate after a null byte. - * Removes access to the raw function rmr_get_meid(ptr, dest) in favor of just rmr_get_meid(ptr). Also get_meid is now rmr_get_meid since it wasn't consistent with the naming. - - -[0.11.0] - 8/21/2019 --------------------- - -:: - * Overhaul unit tests to remove mocking from the rmr tests, which gives much greater confidence in changing the code. More is still needed however, specifically test sends and test receives. - * Adds an alias rmr_set_meid to rmr_bytes2meid for naming consistency. - * Found a possible inconsistency/bug that requires further investigation later; setting meid takes bytes, but getting it returns a string. - - -[0.10.8] - 8/20/2019 --------------------- - -:: - * Fix invocation of _rmr_alloc function - - -[0.10.7] - 8/14/2019 --------------------- - -:: - * Finish sphinx documentation - * Make public functions that wrap ctype declarions, allowing for docstrings - * Fix a bug where rmr_set_stimeout was pointing to the wrong function - - -[0.10.6] - 8/13/2019 --------------------- - -:: - * Moves Changelog.md to this file, to be consistent with rst-ification - * Sets up a Dockerfile to generate documentation for rmr-python using sphinx - - -[0.10.5] - 8/13/2019 --------------------- - -:: - - * Make the PYPI page for rmr look nicer. - -.. _section-1: - -[0.10.4] - 8/08/2019 --------------------- - -:: - - * Fix underlying problem getting errno from some environments; now references new RMR message field to get errno value. - * Add /usr/local/lib64 to tox environment variable to support systems where libraries natually install in lib64 rather than lib. - -.. _section-2: - -[0.10.3] - 7/31/2019 --------------------- - -:: - - * (Correctly) Include license here per Jira RICPLT-1855 - -.. _section-3: - -[0.10.2] - 7/31/2019 --------------------- - -:: - - * Include license here per Jira RICPLT-1855 - -.. _section-4: - -[0.10.0] - 5/15/2019 --------------------- - -:: - - * Fix a bug in rmr mock that prevented it for being used for rmr_rcv (was only usable for rmr_torcv) - * Add more unit tests, esp for message summary - * Remove meid truncation in the case where a nil is present mid string - * Change the defaul mock of meid and get_src to something more useful - -.. _section-5: - -[0.9.0] - 5/13/2019 -------------------- - -:: - - * Add a new module for mocking out rmr-python, useful for other packages that depend on rmr-python - -.. _section-6: - -[0.8.4] - 5/10/2019 -------------------- - -:: - - * Add some unit tests; more to come - -.. _section-7: - -[0.8.3] - 5/8/2019 ------------------- - -:: - - * Better loop indexing in meid string handling - -.. _section-8: - -[0.8.2] - 5/8/2019 ------------------- - -:: - - * Fix examples bug - * add liscneses for LF push - -.. _section-9: - -[0.8.1] - 5/7/2019 ------------------- - -:: - - * Better andling of meid in message summary - -.. _section-10: - -[0.8.0] - 5/7/2019 ------------------- - -:: - - * Refactor some code to be more functional - * Put back RMR_MAX_RCV_BYTES as a constant - * Add tox.ini, although right now it only LINTs - -.. _section-11: - -[0.7.0] - 5/6/2019 ------------------- - -:: - - * Add constant fetching from RMr library - -.. _section-12: - -[0.6.0] - 5/6/2019 ------------------- - -:: - - * Add a new field to rmr_mbuf_t: sub_id - * Fix prior commits lint-ailing python style - -.. _section-13: - -[0.5.0] - 5/3/2019 ------------------- - -:: - - * Add errno access via new function: rmr.errno() - * Add new functions to access new RMr header fields: get_src, get_meid, rmr_bytes2meid - * Add new RMr constants for error states - -.. _section-14: - -[0.4.1] - 4/8/2019 ------------------- - -:: - - * Fix a non-ascii encoding issue - -.. _section-15: - -[0.4.0] - 3/28/2019 -------------------- - -:: - - * Greatly imroved test sender/receiver - * Three new functions implemented (rmr_close, rmr_set_stimeout, rmr_payload_size) - -.. _section-16: - -[0.3.0] - 3/26/2019 -------------------- - -:: - - * Support a new receive function that (hurray!) has a timeout - -.. _section-17: - -[0.2.1] - 3/25/2019 -------------------- - -:: - - * Add two new MR states - -.. _section-18: - -[0.2.0] - 3/25/2019 -------------------- - -:: - - * Switch to NNG from nanomessage - -.. _section-19: - -[0.1.0] - 3/14/2019 -------------------- - -:: - - * Initial Creation diff --git a/src/bindings/rmr-python/docs/source/conf.py b/src/bindings/rmr-python/docs/source/conf.py deleted file mode 100644 index 710078d..0000000 --- a/src/bindings/rmr-python/docs/source/conf.py +++ /dev/null @@ -1,56 +0,0 @@ -# Configuration file for the Sphinx documentation builder. -# -# This file only contains a selection of the most common options. For a full -# list see the documentation: -# http://www.sphinx-doc.org/en/master/config - -# -- Path setup -------------------------------------------------------------- - -# If extensions (or modules to document with autodoc) are in another directory, -# add these directories to sys.path here. If the directory is relative to the -# documentation root, use os.path.abspath to make it absolute, like shown here. -# -import os -import sys - -sys.path.insert(0, os.path.abspath("../../")) - - -# -- Project information ----------------------------------------------------- - -project = "rmr-python" -copyright = "2019, Tommy Carpenter, Scott E Daniels" -author = "Tommy Carpenter, Scott E Daniels" - - -# -- General configuration --------------------------------------------------- - -# Add any Sphinx extension module names here, as strings. They can be -# extensions coming with Sphinx (named 'sphinx.ext.*') or your custom -# ones. -extensions = ["sphinx.ext.autodoc", "sphinx.ext.viewcode", "numpydoc"] - -# Add any paths that contain templates here, relative to this directory. -templates_path = ["_templates"] - -# dont alphabetically order -autodoc_member_order = "bysource" - - -# List of patterns, relative to source directory, that match files and -# directories to ignore when looking for source files. -# This pattern also affects html_static_path and html_extra_path. -exclude_patterns = [] - - -# -- Options for HTML output ------------------------------------------------- - -# The theme to use for HTML and HTML Help pages. See the documentation for -# a list of builtin themes. -# -html_theme = "alabaster" - -# Add any paths that contain custom static files (such as style sheets) here, -# relative to this directory. They are copied after the builtin static files, -# so a file named "default.css" will overwrite the builtin "default.css". -html_static_path = ["_static"] diff --git a/src/bindings/rmr-python/docs/source/index.rst b/src/bindings/rmr-python/docs/source/index.rst deleted file mode 100644 index addb963..0000000 --- a/src/bindings/rmr-python/docs/source/index.rst +++ /dev/null @@ -1,104 +0,0 @@ -rmr-python -========== - -Summary, Limitations -==================== - -This is a CTYPES wrapper around the C rmr library. It requires you have -rmr installed. - -That is, it is not a native re-implementation of the rmr library. This -seems to come with pros and cons. On the positive side, wrapping the -library was much less work; we only need to wrap the function -signatures. Keeping up with the rmr spec is thus also less work, as when -new functions are added into the C lib, we only need to again wrap the -function signatures. - -The downside is this seems to be Linux only currently. This wrapper -immediately SIGABRT's on Mac, and no one yet seems to know why. The -other downside is that there are currently some functionality that needs -to be 'exported' from the C library for this to be fully operational. -For example, CTYPES does not have access to C header files, and -important constants are defined in the C header files. - -Possibly evaluate whether we could natively reimplement the API with the nano nng python -bindings: https://pypi.org/project/pynng/ - -Not Yet Implemented -------------------- - -At the time of this writing (Aug 13 2019) The following C functions -are not yet implemented in this library (do we need them?): - -:: - - 1. `extern void rmr_free_msg` - 2. `extern rmr_mbuf_t* rmr_mtosend_msg` - 3. `extern rmr_mbuf_t* rmr_call` (this has some problems AFAIU from Scott) - 4. `extern rmr_mbuf_t* rmr_rcv_specific` - 5. `extern int rmr_get_rcvfd` - -Unit Testing -============ -You can unit test in docker or outside of docker. -The preferred method (by far) is to use Docker, because it encapsulates rmr, as well as ensuring that ports that rmr opens do not conflict with the host machine - -:: - - docker build -t rmrunittestt:latest -f Dockerfile-Unit-Test . - -A coverage report will be shown in stdout. - -It is possible to run tox locally provided that rmr is intalled, and you are prepared to have the test open ports (4562) as ``rmr_init`` must succeed for the tests to proceed. - -:: - - tox - open htmlcov/index.html - -The added benefit of the local option is that the coverage report can be viewed in html, which I find easier to read than the term coverage reort the docker build will print. - -Installation -============ - -Prequisites ------------ - -If rmr is *not* compiled on your system, see the below instructions for -downloading and compiling rmr. This library expects that the rmr .so -files are compiled and available. - -From PyPi ---------- - -:: - - pip install rmr==X.Y.Z - -From Source ------------ - -:: - - git clone "https://gerrit.o-ran-sc.org/r/ric-plt/lib/rmr" - cd rmr/src/bindings/rmr-python/ - pip install . - -Examples -======== - -See the ``examples`` directory. - -Compiling rmr (if not already done on your system) -================================================== - -(Note, you may or may not need sudo in your final command, depending on -permissions to ``/usr/local``. The pack externals option to CMake is -needed only if the NNG libary is not already installed on the system, -and you do not wish to manually install it.) - -:: - - git clone https://gerrit.oran-osc.org/r/ric-plt/lib/rmr - cd rmr - mkdir .build; cd .build; cmake .. -DPACK_EXTERNALS=1; sudo make install diff --git a/src/bindings/rmr-python/docs/source/module_api.rst b/src/bindings/rmr-python/docs/source/module_api.rst deleted file mode 100644 index 43eb093..0000000 --- a/src/bindings/rmr-python/docs/source/module_api.rst +++ /dev/null @@ -1,16 +0,0 @@ -rmr-python's Module Index -========================== - -rmr.rmr module --------------- - -.. automodule:: rmr.rmr - :members: - -.. rmr.rmr\_mocks.rmr\_mocks module -.. -------------------------------- -.. -.. .. automodule:: rmr.rmr_mocks.rmr_mocks -.. :members: -.. :undoc-members: -.. :private-members: diff --git a/src/bindings/rmr-python/examples/README.md b/src/bindings/rmr-python/examples/README.md deleted file mode 100644 index 671c9b1..0000000 --- a/src/bindings/rmr-python/examples/README.md +++ /dev/null @@ -1,8 +0,0 @@ -# Tests - -First, edit the `local.rt` file with your hostname. - -Start the receiver and the tester. Be sure to set `LD_LIBRARY_PATH` or your system equivelent to point to where the RMR .so files are. On my system (Arch Linux) they are as below. Also, `set -x` is fish shell notation, substitute for your shell. - - set -x LD_LIBRARY_PATH /usr/local/lib/; set -x RMR_SEED_RT ./local.rt; python receive.py - set -x LD_LIBRARY_PATH /usr/local/lib/; set -x RMR_SEED_RT ./local.rt; python send.py diff --git a/src/bindings/rmr-python/examples/local.rt b/src/bindings/rmr-python/examples/local.rt deleted file mode 100644 index 84acffc..0000000 --- a/src/bindings/rmr-python/examples/local.rt +++ /dev/null @@ -1,6 +0,0 @@ -newrt|start -rte|0|devarchwork:4560 -rte|1|devarchwork:4560 -rte|2|devarchwork:4560 -rte|99|devarchwork:4562 -newrt|end diff --git a/src/bindings/rmr-python/examples/rcv_all.py b/src/bindings/rmr-python/examples/rcv_all.py deleted file mode 100644 index 1db982f..0000000 --- a/src/bindings/rmr-python/examples/rcv_all.py +++ /dev/null @@ -1,70 +0,0 @@ -# vim: ts=4 sw=4 expandtab: -# ================================================================================== -# Copyright (c) 2019 Nokia -# Copyright (c) 2018-2019 AT&T Intellectual Property. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. -# ================================================================================== - -# Mnemonic: rcv_all.py -# Abstract: This example shows how to receive all queued messages into -# a bunch (an array of summaries). RMR is initialised in multi- -# threaded call mode so that it will queue messages on a 2K ring -# and prevent the remote application(s) from blocking if we don't -# do timely receives. Then we read 'bursts' of messages sleeping -# between reads to allow some message to pile up. -# -# Because this programme does not send messages, there is no reason -# to wait for RMR to initialise a route table (no call to rmr_ready -# is needed. -# -# Date: 26 September 2019 -# -# --------------------------------------------------------------------------------- - -from rmr import rmr -from rmr import helpers -import time -import sys -import signal - - -# Ensure things terminate nicely -# -def signal_handler(sig, frame): - print('SIGINT received! Cleaning up rmr') - rmr.rmr_close(mrc) - print("Byeee") - sys.exit(0) - -listen_port = "4560".encode('utf-8') # port RMR will listen on (RMR needs string, not value) -mrc = rmr.rmr_init( listen_port, rmr.RMR_MAX_RCV_BYTES, rmr.RMRFL_MTCALL ) # put into multi-threaded call mode - -signal.signal(signal.SIGINT, signal_handler) # cleanup on ctl-c - -while True: - - # three calling options: - #mbunch = helpers.rmr_rcvall_msgs( mrc, [2, 4, 6] ) # get types 2, 4 and 6 only - #mbunch = helpers.rmr_rcvall_msgs( mrc, [2] ) # get types 2 only - mbunch = helpers.rmr_rcvall_msgs( mrc ) # get all message types - - if mbunch == None or len( mbunch ) < 1: - print( "no messages" ) - else: - print( "got %d messages" % len( mbunch ) ) - for mb in mbunch: - print( "type=%d payload=%s" % (mb["message type"], mb["payload"] ) ) - - time.sleep( 1 ) # sleep to allow some to accumulate - diff --git a/src/bindings/rmr-python/examples/receive.py b/src/bindings/rmr-python/examples/receive.py deleted file mode 100644 index 061b79d..0000000 --- a/src/bindings/rmr-python/examples/receive.py +++ /dev/null @@ -1,56 +0,0 @@ -# ================================================================================== -# Copyright (c) 2019 Nokia -# Copyright (c) 2018-2019 AT&T Intellectual Property. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. -# ================================================================================== -from setuptools import setup, find_packages - -from rmr import rmr -import time -import sys -import signal - - -# Demonstrate NNG cleanup -def signal_handler(sig, frame): - print('SIGINT received! Cleaning up rmr') - rmr.rmr_close(mrc) - print("Byeee") - sys.exit(0) - - -# init rmr -mrc = rmr.rmr_init("4560".encode('utf-8'), rmr.RMR_MAX_RCV_BYTES, 0x00) -while rmr.rmr_ready(mrc) == 0: - time.sleep(1) - print("not yet ready") -rmr.rmr_set_stimeout(mrc, 2) - -# capture ctrl-c -signal.signal(signal.SIGINT, signal_handler) - - -sbuf = None -while True: - print("Waiting for a message, will timeout after 2000ms") - sbuf = rmr.rmr_torcv_msg(mrc, sbuf, 2000) - summary = rmr.message_summary(sbuf) - if summary['message state'] == 12: - print("Nothing received =(") - else: - print("Message received!: {}".format(summary)) - val = b"message recieved OK yall!" - rmr.set_payload_and_length(val, sbuf) - sbuf = rmr.rmr_rts_msg(mrc, sbuf) - time.sleep(1) diff --git a/src/bindings/rmr-python/examples/send.py b/src/bindings/rmr-python/examples/send.py deleted file mode 100644 index c6a3703..0000000 --- a/src/bindings/rmr-python/examples/send.py +++ /dev/null @@ -1,64 +0,0 @@ -# ================================================================================== -# Copyright (c) 2019 Nokia -# Copyright (c) 2018-2019 AT&T Intellectual Property. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. -# ================================================================================== -import time -import random -import string -import os -import signal -import sys -from rmr import rmr - - -# Demonstrate NNG cleanup -def signal_handler(sig, frame): - print('SIGINT received! Cleaning up rmr') - rmr.rmr_close(mrc) - print("Byeee") - sys.exit(0) - - -# Init rmr -mrc = rmr.rmr_init(b"4562", rmr.RMR_MAX_RCV_BYTES, 0x00) -while rmr.rmr_ready(mrc) == 0: - time.sleep(1) - print("not yet ready") -rmr.rmr_set_stimeout(mrc, 2) -sbuf = rmr.rmr_alloc_msg(mrc, 256) - -# capture ctrl-c -signal.signal(signal.SIGINT, signal_handler) - -while True: - # generate a random value between 1 and 256 bytes, then gen some random bytes with several nulls thrown in - for val in [''.join([random.choice(string.ascii_letters + string.digits) for n in range(random.randint(1,256))]).encode("utf8"), - b"\x00" + os.urandom(4) + b"\x00" + os.urandom(4) + b"\x00"]: - rmr.set_payload_and_length(val, sbuf) - rmr.generate_and_set_transaction_id(sbuf) - sbuf.contents.state = 0 - sbuf.contents.mtype = 0 - print("Pre send summary: {}".format(rmr.message_summary(sbuf))) - sbuf = rmr.rmr_send_msg(mrc, sbuf) - print("Post send summary: {}".format(rmr.message_summary(sbuf))) - print("Waiting for return, will timeout after 2000ms") - sbuf = rmr.rmr_torcv_msg(mrc, sbuf, 2000) - summary = rmr.message_summary(sbuf) - if summary['message state'] == 12: - print("Nothing received yet") - else: - print("Ack Message received!: {}".format(summary)) - - time.sleep(1) diff --git a/src/bindings/rmr-python/rmr-version.yaml b/src/bindings/rmr-python/rmr-version.yaml deleted file mode 100644 index 07573f1..0000000 --- a/src/bindings/rmr-python/rmr-version.yaml +++ /dev/null @@ -1,3 +0,0 @@ -# CI script installs RMR from PackageCloud using this version ---- -version: 3.6.1 diff --git a/src/bindings/rmr-python/rmr/__init__.py b/src/bindings/rmr-python/rmr/__init__.py deleted file mode 100644 index 121e7af..0000000 --- a/src/bindings/rmr-python/rmr/__init__.py +++ /dev/null @@ -1,16 +0,0 @@ -# ================================================================================== -# Copyright (c) 2019 Nokia -# Copyright (c) 2018-2019 AT&T Intellectual Property. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. -# ================================================================================== diff --git a/src/bindings/rmr-python/rmr/exceptions.py b/src/bindings/rmr-python/rmr/exceptions.py deleted file mode 100644 index c1f1a88..0000000 --- a/src/bindings/rmr-python/rmr/exceptions.py +++ /dev/null @@ -1,31 +0,0 @@ -# ================================================================================== -# Copyright (c) 2019-2020 Nokia -# Copyright (c) 2018-2020 AT&T Intellectual Property. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. -# ================================================================================== -""" -Custom Exceptions -""" - - -class BadBufferAllocation(BaseException): - """a bad buffer was allocated, check the rmr context""" - - -class MeidSizeOutOfRange(BaseException): - """an attempt to set the MEID with a buffer that was too large""" - - -class InitFailed(BaseException): - """rmr init failure, the context is unusable""" diff --git a/src/bindings/rmr-python/rmr/helpers.py b/src/bindings/rmr-python/rmr/helpers.py deleted file mode 100644 index ac4a46e..0000000 --- a/src/bindings/rmr-python/rmr/helpers.py +++ /dev/null @@ -1,102 +0,0 @@ -# vim: ts=4 sw=4 expandtab: -# ================================================================================== -# Copyright (c) 2019 Nokia -# Copyright (c) 2018-2019 AT&T Intellectual Property. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. -# ================================================================================== - -# Mnemonic: helpers.py -# Abstract: This is a colleciton of extensions to the RMR base package -# which are likely to be convenient for python programmes. -# Date: 26 September 2019 -# --------------------------------------------------------------------------- - -from rmr import rmr - - -def rmr_rcvall_msgs(mrc, pass_filter=[]): - """ - Assemble an array of all messages which can be received without - blocking. Effectively draining the message queue if RMR is started - in mt-call mode, or draining any waiting TCP buffers. If the - pass_filter parameter is supplied it is treated as one or more message - types to accept (pass through). Using the default, an empty list, results - in messages with any type being captured. - - Parameters - ---------- - mrc: ctypes c_void_p - Pointer to the RMR context - - pass_filter: list (optional) - The message type(s) to capture. - - Returns - ------- - list of dict - List of message summaries, one for each message captured. - """ - - new_messages = [] - mbuf = rmr.rmr_alloc_msg(mrc, 4096) # allocate buffer to have something for a return status - - while True: - mbuf = rmr.rmr_torcv_msg(mrc, mbuf, 0) # set the timeout to 0 so this doesn't block!! - - summary = rmr.message_summary(mbuf) - if summary["message status"] != "RMR_OK": # ok indicates msg received, stop on all other states - break - - if len(pass_filter) == 0 or summary["message type"] in pass_filter: # no filter, or passes; capture it - new_messages.append(summary) - - rmr.rmr_free_msg(mbuf) # must free message to avoid leak - return new_messages - - -def rmr_rcvall_msgs_raw(mrc, pass_filter=[]): - """ - Same as rmr_rcvall_msgs, but the raw sbuf is also returned. - Useful, for example, if rts is to be used. - - Parameters - ---------- - mrc: ctypes c_void_p - Pointer to the RMR context - - pass_filter: list (optional) - The message type(s) to capture. - - Returns - ------- - list of tuple:$ - List of tuples [(S, sbuf),...] where S is a message summary and sbuf is the raw message$ - the caller is responsible for calling rmr.rmr_free_msg(sbuf) for each sbuf afterwards to prevent memory leaks. - """ - - new_messages = [] - - while True: - mbuf = rmr.rmr_alloc_msg(mrc, 4096) # allocate buffer to have something for a return status - mbuf = rmr.rmr_torcv_msg(mrc, mbuf, 0) # set the timeout to 0 so this doesn't block!! - summary = rmr.message_summary(mbuf) - if summary["message status"] != "RMR_OK": - break - - if len(pass_filter) == 0 or mbuf.contents.mtype in pass_filter: # no filter, or passes; capture it - new_messages.append((summary, mbuf)) - else: - rmr.rmr_free_msg(mbuf) - - return new_messages diff --git a/src/bindings/rmr-python/rmr/rmr.py b/src/bindings/rmr-python/rmr/rmr.py deleted file mode 100644 index 413d8dc..0000000 --- a/src/bindings/rmr-python/rmr/rmr.py +++ /dev/null @@ -1,593 +0,0 @@ -# vim: expandtab ts=4 sw=4: -# ================================================================================== -# Copyright (c) 2019-2020 Nokia -# Copyright (c) 2018-2020 AT&T Intellectual Property. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. -# ================================================================================== -import uuid -import json -from ctypes import RTLD_GLOBAL, Structure, c_int, POINTER, c_char, c_char_p, c_void_p, memmove, cast -from ctypes import CDLL -from ctypes import create_string_buffer -from rmr.exceptions import BadBufferAllocation, MeidSizeOutOfRange, InitFailed - -# https://docs.python.org/3.7/library/ctypes.html -# https://stackoverflow.com/questions/2327344/ctypes-loading-a-c-shared-library-that-has-dependencies/30845750#30845750 -# make sure you do a set -x LD_LIBRARY_PATH /usr/local/lib/; - -# even though we don't use these directly, they contain symbols we need -rmr_c_lib = CDLL("librmr_si.so", mode=RTLD_GLOBAL) - - -# Internal Helpers (not a part of public api) - - -_rmr_const = rmr_c_lib.rmr_get_consts -_rmr_const.argtypes = [] -_rmr_const.restype = c_char_p - - -def _get_constants(cache={}): - """ - Get or build needed constants from rmr - TODO: are there constants that end user applications need? - """ - if cache: - return cache - - js = _rmr_const() # read json string - cache = json.loads(str(js.decode())) # create constants value object as a hash - return cache - - -def _get_mapping_dict(cache={}): - """ - Get or build the state mapping dict - - RMR_OK 0 state is good - RMR_ERR_BADARG 1 argument passd to function was unusable - RMR_ERR_NOENDPT 2 send/call could not find an endpoint based on msg type - RMR_ERR_EMPTY 3 msg received had no payload; attempt to send an empty message - RMR_ERR_NOHDR 4 message didn't contain a valid header - RMR_ERR_SENDFAILED 5 send failed; errno has nano reason - RMR_ERR_CALLFAILED 6 unable to send call() message - RMR_ERR_NOWHOPEN 7 no wormholes are open - RMR_ERR_WHID 8 wormhole id was invalid - RMR_ERR_OVERFLOW 9 operation would have busted through a buffer/field size - RMR_ERR_RETRY 10 request (send/call/rts) failed, but caller should retry (EAGAIN for wrappers) - RMR_ERR_RCVFAILED 11 receive failed (hard error) - RMR_ERR_TIMEOUT 12 message processing call timed out - RMR_ERR_UNSET 13 the message hasn't been populated with a transport buffer - RMR_ERR_TRUNC 14 received message likely truncated - RMR_ERR_INITFAILED 15 initialization of something (probably message) failed - - """ - if cache: - return cache - - rmr_consts = _get_constants() - for key in rmr_consts: # build the state mapping dict - if key[:7] in ["RMR_ERR", "RMR_OK"]: - en = int(rmr_consts[key]) - cache[en] = key - - return cache - - -def _state_to_status(stateno): - """ - Convert a msg state to status - - """ - sdict = _get_mapping_dict() - return sdict.get(stateno, "UNKNOWN STATE") - - -_RCONST = _get_constants() - - -############## -# PUBLIC API -############## - - -# These constants are directly usable by importers of this library -# TODO: Are there others that will be useful? - -RMR_MAX_RCV_BYTES = _RCONST["RMR_MAX_RCV_BYTES"] -RMRFL_MTCALL = _RCONST.get("RMRFL_MTCALL", 0x02) # initialization flags -RMRFL_NONE = _RCONST.get("RMRFL_NONE", 0x0) -RMR_OK = _RCONST["RMR_OK"] # useful state constants -RMR_ERR_TIMEOUT = _RCONST["RMR_ERR_TIMEOUT"] -RMR_ERR_RETRY = _RCONST["RMR_ERR_RETRY"] - - -class rmr_mbuf_t(Structure): - """ - Reimplementation of rmr_mbuf_t which is in an unaccessible header file (src/common/include/rmr.h) - - | typedef struct { - | int state; // state of processing - | int mtype; // message type - | int len; // length of data in the payload (send or received) - | unsigned char* payload; // transported data - | unsigned char* xaction; // pointer to fixed length transaction id bytes - | int sub_id; // subscription id - | int tp_state; // transport state (a.k.a errno) - | - | these things are off limits to the user application - | - | void* tp_buf; // underlying transport allocated pointer (e.g. nng message) - | void* header; // internal message header (whole buffer: header+payload) - | unsigned char* id; // if we need an ID in the message separate from the xaction id - | int flags; // various MFL (private) flags as needed - | int alloc_len; // the length of the allocated space (hdr+payload) - | } rmr_mbuf_t; - - We do not include the fields we are not supposed to mess with - - RE PAYLOADs type below, see the documentation for c_char_p: - class ctypes.c_char_p - Represents the C char * datatype when it points to a zero-terminated string. For a general character pointer that may also point to binary data, POINTER(c_char) must be used. The constructor accepts an integer address, or a bytes object. - """ - - _fields_ = [ - ("state", c_int), - ("mtype", c_int), - ("len", c_int), - ( - "payload", - POINTER(c_char), - ), # according to th following the python bytes are already unsinged https://bytes.com/topic/python/answers/695078-ctypes-unsigned-char - ("xaction", POINTER(c_char)), - ("sub_id", c_int), - ("tp_state", c_int), - ] - - -# argtypes and restype are important: https://stackoverflow.com/questions/24377845/ctype-why-specify-argtypes - - -_rmr_init = rmr_c_lib.rmr_init -_rmr_init.argtypes = [c_char_p, c_int, c_int] -_rmr_init.restype = c_void_p - - -def rmr_init(uproto_port, max_msg_size, flags): - """ - Refer to rmr C documentation for rmr_init - extern void* rmr_init(char* uproto_port, int max_msg_size, int flags) - - This python function checks that the context is not None and raises - an excption if it is. - """ - mrc = _rmr_init(uproto_port, max_msg_size, flags) - if mrc is None: - raise InitFailed() - return mrc - - -_rmr_ready = rmr_c_lib.rmr_ready -_rmr_ready.argtypes = [c_void_p] -_rmr_ready.restype = c_int - - -def rmr_ready(vctx): - """ - Refer to rmr C documentation for rmr_ready - extern int rmr_ready(void* vctx) - """ - return _rmr_ready(vctx) - - -_rmr_close = rmr_c_lib.rmr_close -_rmr_close.argtypes = [c_void_p] - - -def rmr_close(vctx): - """ - Refer to rmr C documentation for rmr_close - extern void rmr_close(void* vctx) - """ - return _rmr_close(vctx) - - -_rmr_set_stimeout = rmr_c_lib.rmr_set_stimeout -_rmr_set_stimeout.argtypes = [c_void_p, c_int] -_rmr_set_stimeout.restype = c_int - - -def rmr_set_stimeout(vctx, time): - """ - Refer to the rmr C documentation for rmr_set_stimeout - extern int rmr_set_stimeout(void* vctx, int time) - """ - return _rmr_set_stimeout(vctx, time) - - -_rmr_alloc_msg = rmr_c_lib.rmr_alloc_msg -_rmr_alloc_msg.argtypes = [c_void_p, c_int] -_rmr_alloc_msg.restype = POINTER(rmr_mbuf_t) - - -def rmr_alloc_msg( - vctx, size, payload=None, gen_transaction_id=False, mtype=None, meid=None, sub_id=None, fixed_transaction_id=None -): - """ - Refer to the rmr C documentation for rmr_alloc_msg - extern rmr_mbuf_t* rmr_alloc_msg(void* vctx, int size) - TODO: on next API break, clean up transaction_id ugliness. Kept for now to preserve API. - - if payload is not None, attempts to set the payload - if gen_transaction_id is True, it generates and sets a transaction id. Note, fixed_transaction_id supersedes this option - if mtype is not None, sets the sbuf's message type - if meid is not None, sets the sbuf's meid - if sub_id is not None, sets the sbud's subscription id - if fixed_transaction_id is set, it deterministically sets the transaction_id. This overrides the option gen_transation_id - - """ - sbuf = _rmr_alloc_msg(vctx, size) - try: - # make sure the alloc worked - sbuf.contents - - # set specified fields - if payload: - set_payload_and_length(payload, sbuf) - - if fixed_transaction_id: - set_transaction_id(sbuf, fixed_transaction_id) - elif gen_transaction_id: - generate_and_set_transaction_id(sbuf) - - if mtype: - sbuf.contents.mtype = mtype - - if meid: - rmr_set_meid(sbuf, meid) - - if sub_id: - sbuf.contents.sub_id = sub_id - - return sbuf - - except ValueError: - raise BadBufferAllocation - - -_rmr_realloc_payload = rmr_c_lib.rmr_realloc_payload -_rmr_realloc_payload.argtypes = [POINTER(rmr_mbuf_t), c_int, c_int, c_int] # new_len, copy, clone -_rmr_realloc_payload.restype = POINTER(rmr_mbuf_t) - - -def rmr_realloc_payload(ptr_mbuf, new_len, copy=False, clone=False): - """ - Refer to the rmr C documentation for rmr_realloc_payload(). - extern rmr_mbuf_t* rmr_realloc_payload(rmr_mbuf_t*, int, int, int) - """ - return _rmr_realloc_payload(ptr_mbuf, new_len, copy, clone) - - -_rmr_free_msg = rmr_c_lib.rmr_free_msg -_rmr_free_msg.argtypes = [c_void_p] -_rmr_free_msg.restype = None - - -def rmr_free_msg(mbuf): - """ - Refer to the rmr C documentation for rmr_free_msg - extern void rmr_free_msg(rmr_mbuf_t* mbuf ) - """ - if mbuf is not None: - _rmr_free_msg(mbuf) - - -_rmr_payload_size = rmr_c_lib.rmr_payload_size -_rmr_payload_size.argtypes = [POINTER(rmr_mbuf_t)] -_rmr_payload_size.restype = c_int - - -def rmr_payload_size(ptr_mbuf): - """ - Refer to the rmr C documentation for rmr_payload_size - extern int rmr_payload_size(rmr_mbuf_t* msg) - """ - return _rmr_payload_size(ptr_mbuf) - - -""" -The following functions all seem to have the same interface -""" - -_rmr_send_msg = rmr_c_lib.rmr_send_msg -_rmr_send_msg.argtypes = [c_void_p, POINTER(rmr_mbuf_t)] -_rmr_send_msg.restype = POINTER(rmr_mbuf_t) - - -def rmr_send_msg(vctx, ptr_mbuf): - """ - Refer to the rmr C documentation for rmr_send_msg - extern rmr_mbuf_t* rmr_send_msg(void* vctx, rmr_mbuf_t* msg) - """ - return _rmr_send_msg(vctx, ptr_mbuf) - - -# TODO: the old message (Send param) is actually optional, but I don't know how to specify that in Ctypes. -_rmr_rcv_msg = rmr_c_lib.rmr_rcv_msg -_rmr_rcv_msg.argtypes = [c_void_p, POINTER(rmr_mbuf_t)] -_rmr_rcv_msg.restype = POINTER(rmr_mbuf_t) - - -def rmr_rcv_msg(vctx, ptr_mbuf): - """ - Refer to the rmr C documentation for rmr_rcv_msg - extern rmr_mbuf_t* rmr_rcv_msg(void* vctx, rmr_mbuf_t* old_msg) - """ - return _rmr_rcv_msg(vctx, ptr_mbuf) - - -_rmr_torcv_msg = rmr_c_lib.rmr_torcv_msg -_rmr_torcv_msg.argtypes = [c_void_p, POINTER(rmr_mbuf_t), c_int] -_rmr_torcv_msg.restype = POINTER(rmr_mbuf_t) - - -def rmr_torcv_msg(vctx, ptr_mbuf, ms_to): - """ - Refer to the rmr C documentation for rmr_torcv_msg - extern rmr_mbuf_t* rmr_torcv_msg(void* vctx, rmr_mbuf_t* old_msg, int ms_to) - """ - return _rmr_torcv_msg(vctx, ptr_mbuf, ms_to) - - -_rmr_rts_msg = rmr_c_lib.rmr_rts_msg -_rmr_rts_msg.argtypes = [c_void_p, POINTER(rmr_mbuf_t)] -_rmr_rts_msg.restype = POINTER(rmr_mbuf_t) - - -def rmr_rts_msg(vctx, ptr_mbuf, payload=None, mtype=None): - """ - Refer to the rmr C documentation for rmr_rts_msg - extern rmr_mbuf_t* rmr_rts_msg(void* vctx, rmr_mbuf_t* msg) - - additional features beyond c-rmr: - if payload is not None, attempts to set the payload - if mtype is not None, sets the sbuf's message type - """ - - if payload: - set_payload_and_length(payload, ptr_mbuf) - - if mtype: - ptr_mbuf.contents.mtype = mtype - - return _rmr_rts_msg(vctx, ptr_mbuf) - - -_rmr_call = rmr_c_lib.rmr_call -_rmr_call.argtypes = [c_void_p, POINTER(rmr_mbuf_t)] -_rmr_call.restype = POINTER(rmr_mbuf_t) - - -def rmr_call(vctx, ptr_mbuf): - """ - Refer to the rmr C documentation for rmr_call - extern rmr_mbuf_t* rmr_call(void* vctx, rmr_mbuf_t* msg) - """ - return _rmr_call(vctx, ptr_mbuf) - - -_rmr_bytes2meid = rmr_c_lib.rmr_bytes2meid -_rmr_bytes2meid.argtypes = [POINTER(rmr_mbuf_t), c_char_p, c_int] -_rmr_bytes2meid.restype = c_int - - -def rmr_set_meid(ptr_mbuf, byte_str): - """ - Refer to the rmr C documentation for rmr_bytes2meid - extern int rmr_bytes2meid(rmr_mbuf_t* mbuf, unsigned char const* src, int len); - - Caution: the meid length supported in an RMR message is 32 bytes, but C applications - expect this to be a nil terminated string and thus only 31 bytes are actually available. - - Raises: exceptions.MeidSizeOutOfRang - """ - max = _get_constants().get("RMR_MAX_MEID", 32) - if len(byte_str) >= max: - raise MeidSizeOutOfRange - - return _rmr_bytes2meid(ptr_mbuf, byte_str, len(byte_str)) - - -# CAUTION: Some of the C functions expect a mutable buffer to copy the bytes into; -# if there is a get_* function below, use it to set up and return the -# buffer properly. - -# extern unsigned char* rmr_get_meid(rmr_mbuf_t* mbuf, unsigned char* dest); -# we don't provide direct access to this function (unless it is asked for) because it is not really useful to provide your own buffer. -# Rather, rmr_get_meid does this for you, and just returns the string. -_rmr_get_meid = rmr_c_lib.rmr_get_meid -_rmr_get_meid.argtypes = [POINTER(rmr_mbuf_t), c_char_p] -_rmr_get_meid.restype = c_char_p - - -def rmr_get_meid(ptr_mbuf): - """ - Get the managed equipment ID (meid) from the message header. - - Parameters - ---------- - ptr_mbuf: ctypes c_void_p - Pointer to an rmr message buffer - - Returns - ------- - string: - meid - """ - sz = _get_constants().get("RMR_MAX_MEID", 32) # size for buffer to fill - buf = create_string_buffer(sz) - _rmr_get_meid(ptr_mbuf, buf) - return buf.value - - -_rmr_get_src = rmr_c_lib.rmr_get_src -_rmr_get_src.argtypes = [POINTER(rmr_mbuf_t), c_char_p] -_rmr_get_src.restype = c_char_p - - -def rmr_get_src(ptr_mbuf, dest): - """ - Refer to the rmr C documentation for rmr_get_src - extern unsigned char* rmr_get_src(rmr_mbuf_t* mbuf, unsigned char* dest); - """ - return _rmr_get_src(ptr_mbuf, dest) - - -# Methods that exist ONLY in rmr-python, and are not wrapped methods -# In hindsight, I wish i put these in a seperate module, but leaving this here to prevent api breakage. - - -def get_payload(ptr_mbuf): - """ - Given a rmr_buf_t*, get it's binary payload as a bytes object - - Parameters - ---------- - ptr_mbuf: ctypes c_void_p - Pointer to an rmr message buffer - - Returns - ------- - bytes: - the message payload - """ - # Logic came from the answer here: https://stackoverflow.com/questions/55103298/python-ctypes-read-pointerc-char-in-python - sz = ptr_mbuf.contents.len - CharArr = c_char * sz - return CharArr(*ptr_mbuf.contents.payload[:sz]).raw - - -def get_xaction(ptr_mbuf): - """ - given a rmr_buf_t*, get it's transaction id - - Parameters - ---------- - ptr_mbuf: ctypes c_void_p - Pointer to an rmr message buffer - - Returns - ------- - bytes: - the transaction id - """ - val = cast(ptr_mbuf.contents.xaction, c_char_p).value - sz = _get_constants().get("RMR_MAX_XID", 0) - return val[:sz] - - -def message_summary(ptr_mbuf): - """ - Returns a dict that contains the fields of a message - - Parameters - ---------- - ptr_mbuf: ctypes c_void_p - Pointer to an rmr message buffer - - Returns - ------- - dict: - dict message summary - """ - return { - "payload": get_payload(ptr_mbuf) if ptr_mbuf.contents.state == RMR_OK else None, - "payload length": ptr_mbuf.contents.len, - "message type": ptr_mbuf.contents.mtype, - "subscription id": ptr_mbuf.contents.sub_id, - "transaction id": get_xaction(ptr_mbuf), - "message state": ptr_mbuf.contents.state, - "message status": _state_to_status(ptr_mbuf.contents.state), - "payload max size": rmr_payload_size(ptr_mbuf), - "meid": rmr_get_meid(ptr_mbuf), - "message source": get_src(ptr_mbuf), - "errno": ptr_mbuf.contents.tp_state, - } - - -def set_payload_and_length(byte_str, ptr_mbuf): - """ - | Set an rmr payload and content length - | In place method, no return - - Parameters - ---------- - byte_str: bytes - the bytes to set the payload to - ptr_mbuf: ctypes c_void_p - Pointer to an rmr message buffer - """ - if rmr_payload_size(ptr_mbuf) < len(byte_str): # existing message payload too small - ptr_mbuf = rmr_realloc_payload(ptr_mbuf, len(byte_str), True) - - memmove(ptr_mbuf.contents.payload, byte_str, len(byte_str)) - ptr_mbuf.contents.len = len(byte_str) - - -def generate_and_set_transaction_id(ptr_mbuf): - """ - Generate a UUID and Set an rmr transaction id to it - - Parameters - ---------- - ptr_mbuf: ctypes c_void_p - Pointer to an rmr message buffer - """ - set_transaction_id(ptr_mbuf, uuid.uuid1().hex.encode("utf-8")) - - -def set_transaction_id(ptr_mbuf, tid_bytes): - """ - Set an rmr transaction id - TODO: on next API break, merge these two functions. Not done now to preserve API. - - Parameters - ---------- - ptr_mbuf: ctypes c_void_p - Pointer to an rmr message buffer - tid_bytes: bytes - bytes of the desired transaction id - """ - sz = _get_constants().get("RMR_MAX_XID", 0) - memmove(ptr_mbuf.contents.xaction, tid_bytes, sz) - - -def get_src(ptr_mbuf): - """ - Get the message source (likely host:port) - - Parameters - ---------- - ptr_mbuf: ctypes c_void_p - Pointer to an rmr message buffer - - Returns - ------- - string: - message source - """ - sz = _get_constants().get("RMR_MAX_SRC", 64) # size to fill - buf = create_string_buffer(sz) - rmr_get_src(ptr_mbuf, buf) - return buf.value.decode() diff --git a/src/bindings/rmr-python/rmr/rmr_mocks/__init__.py b/src/bindings/rmr-python/rmr/rmr_mocks/__init__.py deleted file mode 100644 index e69de29..0000000 diff --git a/src/bindings/rmr-python/rmr/rmr_mocks/rmr_mocks.py b/src/bindings/rmr-python/rmr/rmr_mocks/rmr_mocks.py deleted file mode 100644 index b498511..0000000 --- a/src/bindings/rmr-python/rmr/rmr_mocks/rmr_mocks.py +++ /dev/null @@ -1,156 +0,0 @@ -# ================================================================================== -# Copyright (c) 2019 Nokia -# Copyright (c) 2018-2019 AT&T Intellectual Property. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. -# ================================================================================== - -""" -Provides mocks that are useful for end applications unit testing -""" - -import json -import uuid - - -def rcv_mock_generator(msg_payload, msg_type, msg_state, jsonb, timeout=0): - """ - generates a mock function that can be used to monkeypatch rmr_torcv_msg or rmr_rcv_msg - """ - - def f(_mrc, sbuf, _timeout=timeout): # last param is needed for calls to rmr_torcv_msg, but not in rmr_rcv_msg - sbuf.contents.mtype = msg_type - payload = json.dumps(msg_payload).encode("utf-8") if jsonb else msg_payload - sbuf.contents.payload = payload - sbuf.contents.len = len(payload) - sbuf.contents.state = msg_state - if msg_state != 0: # set something in transport state if 'error' - sbuf.contents.tp_state = 99 - else: - sbuf.contents.tp_state = 0 - return sbuf - - return f - - -def send_mock_generator(msg_state): - """ - generates a mock function that can be used to monkeypatch rmr_send_msg - usage example: - monkeypatch.setattr('rmr.rmr.rmr_send_msg', rmr_mocks.send_mock_generator(0)) - """ - - def f(_unused, sbuf): - sbuf.contents.state = msg_state - if msg_state != 0: # set something in transport state if 'error' - sbuf.contents.tp_state = 99 - else: - sbuf.contents.tp_state = 0 - return sbuf - - return f - - -class _Sbuf_Contents: - """fake version of how pointers work (ctype pointer access is done by accessing a magical attrivute called "contents""" - - def __init__(self): - self.state = 0 - self.mtype = 0 - self.len = 0 - self.payload = "" - self.xaction = uuid.uuid1().hex.encode("utf-8") - self.sub_id = 0 - self.tp_state = 0 - self.meid = None - - def __str__(self): - return str( - { - "state": self.state, - "mtype": self.mtype, - "len": self.len, - "payload": self.payload, - "xaction": self.xaction, - "sub_id": self.sub_id, - "tp_state": self.tp_state, - "meid": self.meid, - } - ) - - -class Rmr_mbuf_t: - """fake version of rmr.rmr_mbuf_t""" - - def __init__(self): - self.contents = _Sbuf_Contents() - - -def patch_rmr(monkeypatch): - """ - Patch rmr; requires a monkeypatch (pytest) object to be passed in - """ - - def fake_alloc( - _vctx, _sz, payload=None, gen_transaction_id=False, mtype=None, meid=None, sub_id=None, fixed_transaction_id=None - ): - sbuf = Rmr_mbuf_t() - if payload: - sbuf.contents.payload = payload - - if fixed_transaction_id: - sbuf.contents.xaction = fixed_transaction_id - elif gen_transaction_id: - sbuf.contents.xaction = uuid.uuid1().hex.encode("utf-8") - - if mtype: - sbuf.contents.mtype = mtype - - if meid: - sbuf.contents.meid = meid - - if sub_id: - sbuf.contents.sub_id = sub_id - - return sbuf - - def fake_set_payload_and_length(payload, sbuf): - sbuf.contents.payload = payload - sbuf.contents.len = len(payload) - - def fake_generate_and_set_transaction_id(sbuf): - sbuf.contents.xaction = uuid.uuid1().hex.encode("utf-8") - - def fake_get_payload(sbuf): - return sbuf.contents.payload - - def fake_get_meid(sbuf): - return sbuf.contents.meid - - def fake_get_src(_sbuf): - return "localtest:80" # this is not a part of rmr_mbuf_t - - def fake_rmr_payload_size(_sbuf): - return 4096 - - def fake_free(_sbuf): - pass - - monkeypatch.setattr("rmr.rmr.rmr_free_msg", fake_free) - monkeypatch.setattr("rmr.rmr.rmr_alloc_msg", fake_alloc) - monkeypatch.setattr("rmr.rmr.set_payload_and_length", fake_set_payload_and_length) - monkeypatch.setattr("rmr.rmr.generate_and_set_transaction_id", fake_generate_and_set_transaction_id) - monkeypatch.setattr("rmr.rmr.get_payload", fake_get_payload) - monkeypatch.setattr("rmr.rmr.get_src", fake_get_src) - monkeypatch.setattr("rmr.rmr.rmr_get_meid", fake_get_meid) - monkeypatch.setattr("rmr.rmr.rmr_payload_size", fake_rmr_payload_size) diff --git a/src/bindings/rmr-python/setup.py b/src/bindings/rmr-python/setup.py deleted file mode 100644 index 0171edb..0000000 --- a/src/bindings/rmr-python/setup.py +++ /dev/null @@ -1,56 +0,0 @@ -# ================================================================================== -# Copyright (c) 2020 Nokia -# Copyright (c) 2018-2020 AT&T Intellectual Property. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. -# ================================================================================== -from os.path import dirname, abspath, join as path_join -from setuptools import setup, find_packages - -SETUP_DIR = abspath(dirname(__file__)) - - -def _long_descr(): - """Yields the content of documentation files for the long description""" - try: - doc_path = path_join(SETUP_DIR, "docs/source/index.rst") - with open(doc_path) as f: - return f.read() - except FileNotFoundError: # this happens during unit testing, we don't need it - return "" - - -setup( - name="rmr", - version="4.0.0", - packages=find_packages(), - author="Tommy Carpenter, E. Scott Daniels", - description="Python wrapper for RIC RMR", - url="https://gerrit.o-ran-sc.org/r/admin/repos/ric-plt/lib/rmr", - classifiers=[ - "Development Status :: 4 - Beta", - "Intended Audience :: Telecommunications Industry", - "Programming Language :: Python :: 3", - "Programming Language :: Python :: 3.7", - "License :: OSI Approved :: Apache Software License", - "Operating System :: POSIX :: Linux", - "Topic :: Communications", - ], - python_requires=">=3.7", - keywords="RIC rmr", - license="Apache 2.0", - data_files=[("", ["LICENSE.txt"])], - install_requires=[], - long_description=_long_descr(), - long_description_content_type="text/x-rst", -) diff --git a/src/bindings/rmr-python/tests/conftest.py b/src/bindings/rmr-python/tests/conftest.py deleted file mode 100644 index e29c779..0000000 --- a/src/bindings/rmr-python/tests/conftest.py +++ /dev/null @@ -1,78 +0,0 @@ -# vim: ts=4 sw=4 expandtab: -# ================================================================================== -# Copyright (c) 2019 Nokia -# Copyright (c) 2018-2019 AT&T Intellectual Property. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. -# ================================================================================== -import pytest - - -# These are here just to reduce the size of the code in test_rmr so those (important) tests are more readable; in theory these dicts could be large -# The actual value of the constants should be ignored by the tests; all we should care -# about is that the constant value was returned by the RMR function. Further, we should -# not consider it an error if RMR returns more than what is listed here; these are the -# list of what is/could be used by this package. -@pytest.fixture -def expected_constants(): - return { - "RMR_MAX_XID": 32, - "RMR_MAX_SID": 32, - "RMR_MAX_MEID": 32, - "RMR_MAX_SRC": 64, - "RMR_MAX_RCV_BYTES": 4096, - "RMRFL_NONE": 0, - "RMRFL_MTCALL": 2, # can't be added here until jenkins version >= 1.8.3 - "RMRFL_AUTO_ALLOC": 3, - "RMR_DEF_SIZE": 0, - "RMR_VOID_MSGTYPE": -1, - "RMR_VOID_SUBID": -1, - "RMR_OK": 0, - "RMR_ERR_BADARG": 1, - "RMR_ERR_NOENDPT": 2, - "RMR_ERR_EMPTY": 3, - "RMR_ERR_NOHDR": 4, - "RMR_ERR_SENDFAILED": 5, - "RMR_ERR_CALLFAILED": 6, - "RMR_ERR_NOWHOPEN": 7, - "RMR_ERR_WHID": 8, - "RMR_ERR_OVERFLOW": 9, - "RMR_ERR_RETRY": 10, - "RMR_ERR_RCVFAILED": 11, - "RMR_ERR_TIMEOUT": 12, - "RMR_ERR_UNSET": 13, - "RMR_ERR_TRUNC": 14, - "RMR_ERR_INITFAILED": 15, - } - - -@pytest.fixture -def expected_states(): - return { - 0: "RMR_OK", - 1: "RMR_ERR_BADARG", - 2: "RMR_ERR_NOENDPT", - 3: "RMR_ERR_EMPTY", - 4: "RMR_ERR_NOHDR", - 5: "RMR_ERR_SENDFAILED", - 6: "RMR_ERR_CALLFAILED", - 7: "RMR_ERR_NOWHOPEN", - 8: "RMR_ERR_WHID", - 9: "RMR_ERR_OVERFLOW", - 10: "RMR_ERR_RETRY", - 11: "RMR_ERR_RCVFAILED", - 12: "RMR_ERR_TIMEOUT", - 13: "RMR_ERR_UNSET", - 14: "RMR_ERR_TRUNC", - 15: "RMR_ERR_INITFAILED", - } diff --git a/src/bindings/rmr-python/tests/fixtures/test_local.rt b/src/bindings/rmr-python/tests/fixtures/test_local.rt deleted file mode 100644 index e77afac..0000000 --- a/src/bindings/rmr-python/tests/fixtures/test_local.rt +++ /dev/null @@ -1,8 +0,0 @@ -# do NOT use localhost, seems unresolved on jenkins VMs -# the 4563 lines are used by MRC_RCV; the 4564 are used by MRC_BUF_RCV -newrt|start -mse| 0 | -1 | 127.0.0.1:4563 -mse| 46656 | 777 | 127.0.0.1:4563 -mse| 1 | -1 | 127.0.0.1:4564 -mse| 2 | -1 | 127.0.0.1:4564 -newrt|end diff --git a/src/bindings/rmr-python/tests/test_rmr.py b/src/bindings/rmr-python/tests/test_rmr.py deleted file mode 100644 index 33b61f7..0000000 --- a/src/bindings/rmr-python/tests/test_rmr.py +++ /dev/null @@ -1,373 +0,0 @@ -# vim: ts=4 sw=4 expandtab: -# =================================================================================2 -# Copyright (c) 2019-2020 Nokia -# Copyright (c) 2018-2020 AT&T Intellectual Property. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. -# ================================================================================== -import time -import pytest -from rmr import rmr, helpers, exceptions - - -SIZE = 256 -MRC_SEND = None -MRC_RCV = None - - -def setup_module(): - """ - test_rmr module setup - """ - global MRC_SEND - MRC_SEND = rmr.rmr_init(b"4562", rmr.RMR_MAX_RCV_BYTES, 0x00) - while rmr.rmr_ready(MRC_SEND) == 0: - time.sleep(1) - - global MRC_RCV - MRC_RCV = rmr.rmr_init(b"4563", rmr.RMR_MAX_RCV_BYTES, 0x00) - while rmr.rmr_ready(MRC_RCV) == 0: - time.sleep(1) - - global MRC_BUF_RCV - MRC_BUF_RCV = rmr.rmr_init(b"4564", rmr.RMR_MAX_RCV_BYTES, 0x02) - while rmr.rmr_ready(MRC_BUF_RCV) == 0: - time.sleep(1) - - -def teardown_module(): - """ - test rmr module teardown - """ - rmr.rmr_close(MRC_SEND) - rmr.rmr_close(MRC_RCV) - - -def _assert_new_sbuf(sbuf): - """ - verify the initial state of an alloced message is what we expect - """ - summary = rmr.message_summary(sbuf) - assert summary["payload"] == b"" - assert summary["payload length"] == 0 - assert summary["subscription id"] == -1 - assert summary["transaction id"] == b"" - assert summary["message state"] == 0 - assert summary["message status"] == "RMR_OK" - assert summary["meid"] == b"" - assert summary["errno"] == 0 - - -def test_get_constants(expected_constants): - """ - test getting constants. We don't care what values are returned as those - should be meaningful only to RMR. We do care that all of the constants - which are defined in expected_contents are returned. Further, we don't - consider it to be an error if the returned list has more constants than - what are in our list. - - To avoid frustration, this should list all missing keys, not fail on the - first missing key. - """ - errors = 0 - econst = expected_constants - rconst = rmr._get_constants() - for key in econst: # test all expected constants - if key not in rconst: # expected value not listed by rmr - errors += 1 - print("did not find required constant in list from RMR: %s" % key) - - assert errors == 0 - - -def test_get_mapping_dict(expected_states): - """ - test getting mapping string - """ - assert rmr._get_mapping_dict() == expected_states - assert rmr._state_to_status(0) == "RMR_OK" - assert rmr._state_to_status(12) == "RMR_ERR_TIMEOUT" - assert rmr._state_to_status(666) == "UNKNOWN STATE" - - -def test_meid(): - """ - test meid stringification - """ - sbuf = rmr.rmr_alloc_msg(MRC_SEND, SIZE) - - rmr.rmr_set_meid(sbuf, b"\x01\x02") - assert rmr.rmr_get_meid(sbuf) == rmr.message_summary(sbuf)["meid"] == b"\x01\x02" - assert len(rmr.rmr_get_meid(sbuf)) == 2 - - rmr.rmr_set_meid(sbuf, b"\x00" * 31) - assert rmr.rmr_get_meid(sbuf) == rmr.message_summary(sbuf)["meid"] == b"" # NULL bytes get truncated - - rmr.rmr_set_meid(sbuf, b"6" * 31) - assert rmr.rmr_get_meid(sbuf) == rmr.message_summary(sbuf)["meid"] == b"6" * 31 # string in string out - - rmr.rmr_set_meid(sbuf, b"\x01\x02") - assert ( - rmr.rmr_get_meid(sbuf) == rmr.message_summary(sbuf)["meid"] == b"\x01\x02" - ) # Ctypes will chop at first nil, so expect only 2 bytes back - - assert len(rmr.rmr_get_meid(sbuf)) == 2 - - # test that an exception is raised for buffers which are too long - with pytest.raises(exceptions.MeidSizeOutOfRange): - rmr.rmr_set_meid(sbuf, b"8" * 32) - - - -def test_rmr_set_get(): - """ - test set functions - """ - sbuf = rmr.rmr_alloc_msg(MRC_SEND, SIZE) - _assert_new_sbuf(sbuf) - - # test payload - pay = b"\x01\x00\x80" - rmr.set_payload_and_length(pay, sbuf) - summary = rmr.message_summary(sbuf) - assert summary["payload"] == pay - assert summary["payload length"] == 3 - - # test transid (note we cant test payload because it's randomly gen) - assert summary["transaction id"] == b"" - assert len(summary["transaction id"]) == 0 - rmr.generate_and_set_transaction_id(sbuf) - summary = rmr.message_summary(sbuf) - assert summary["transaction id"] != b"" - assert len(summary["transaction id"]) == 32 - - # test meid - assert rmr.rmr_get_meid(sbuf) == summary["meid"] == b"" - rmr.rmr_set_meid(sbuf, b"666\x01\x00\x01") - summary = rmr.message_summary(sbuf) - assert rmr.rmr_get_meid(sbuf) == summary["meid"] == b"666\x01" - assert (len(summary["meid"])) == 4 - - -def test_alloc_fancy(): - """test allocation with setting payload, trans, mtype, subid""" - pay = b"yoo\x01\x00\x80" - sbuf = rmr.rmr_alloc_msg(MRC_SEND, SIZE, payload=pay, gen_transaction_id=True, mtype=14, meid=b"asdf", sub_id=654321) - summary = rmr.message_summary(sbuf) - assert summary["payload"] == pay - assert summary["payload length"] == 6 - assert summary["transaction id"] != b"" # hard to test what it will be, but make sure not empty - assert len(summary["transaction id"]) == 32 - assert summary["message state"] == 0 - assert summary["message type"] == sbuf.contents.mtype == 14 - assert rmr.rmr_get_meid(sbuf) == summary["meid"] == b"asdf" - assert sbuf.contents.sub_id == summary["subscription id"] == 654321 - - -def test_alloc_overlapping_flags(): - """test allocation with setting the transaction id""" - sbuf = rmr.rmr_alloc_msg(MRC_SEND, SIZE, gen_transaction_id=True, fixed_transaction_id=b"6" * 32) - summary = rmr.message_summary(sbuf) - assert summary["transaction id"] == b"66666666666666666666666666666666" - - -def test_rcv_timeout(): - """ - test torcv; this is a scary test because if it fails... it doesn't fail, it will run forever! - We receive a message (though nothing has been sent) and make sure the function doesn't block forever. - - There is no unit test for rmr_rcv_msg; too dangerous, that is a blocking call that may never return. - """ - sbuf_rcv = rmr.rmr_alloc_msg(MRC_RCV, SIZE) - sbuf_rcv = rmr.rmr_torcv_msg(MRC_RCV, sbuf_rcv, 50) # should time out after 50ms - summary = rmr.message_summary(sbuf_rcv) - assert summary["message state"] == 12 - assert summary["message status"] == "RMR_ERR_TIMEOUT" - - -def test_send_rcv(): - """ - test send and receive - """ - pay = b"\x01\x00\x80" - - # send a message - sbuf_send = rmr.rmr_alloc_msg(MRC_SEND, SIZE) - _assert_new_sbuf(sbuf_send) - rmr.set_payload_and_length(pay, sbuf_send) - sbuf_send.contents.mtype = 0 - sbuf_send = rmr.rmr_send_msg(MRC_SEND, sbuf_send) - send_summary = rmr.message_summary(sbuf_send) - assert send_summary["message state"] == 0 # if send fails don't attempt receive - assert send_summary["message status"] == "RMR_OK" - time.sleep(0.5) - - # receive it in other context - sbuf_rcv = rmr.rmr_alloc_msg(MRC_RCV, SIZE) - sbuf_rcv = rmr.rmr_torcv_msg(MRC_RCV, sbuf_rcv, 2000) - rcv_summary = rmr.message_summary(sbuf_rcv) - assert rcv_summary["message state"] == 0 - assert rcv_summary["message status"] == "RMR_OK" - assert rcv_summary["message type"] == 0 - assert rcv_summary["payload"] == pay - - # send an ACK back - ack_pay = b"message received" - sbuf_rcv = rmr.rmr_rts_msg(MRC_RCV, sbuf_rcv, payload=ack_pay, mtype=6666) - rcv_ack_summary = rmr.message_summary(sbuf_rcv) - - # have the sender receive it - sbuf_send = rmr.rmr_torcv_msg(MRC_SEND, sbuf_send, 2000) - send_ack_summary = rmr.message_summary(sbuf_send) - - assert send_ack_summary["message state"] == rcv_ack_summary["message state"] == 0 - assert send_ack_summary["message status"] == rcv_ack_summary["message status"] == "RMR_OK" - assert send_ack_summary["payload"] == ack_pay - assert send_ack_summary["message type"] == 6666 - - -def test_send_rcv_subid_good(): - """ - test send and receive where subid is used for routing - """ - pay = b"\x01\x00\x80" - test_mtype = 46656 - test_subid = 777 - - # send a message - sbuf_send = rmr.rmr_alloc_msg(MRC_SEND, 3, pay, mtype=test_mtype, sub_id=test_subid) - pre_send_summary = rmr.message_summary(sbuf_send) - sbuf_send = rmr.rmr_send_msg(MRC_SEND, sbuf_send) - send_summary = rmr.message_summary(sbuf_send) - - # receive it in other context - time.sleep(0.5) - sbuf_rcv = rmr.rmr_alloc_msg(MRC_RCV, 3) - sbuf_rcv = rmr.rmr_torcv_msg(MRC_RCV, sbuf_rcv, 2000) - rcv_summary = rmr.message_summary(sbuf_rcv) - - # asserts - assert send_summary["message state"] == rcv_summary["message state"] == 0 - assert send_summary["message status"] == rcv_summary["message status"] == "RMR_OK" - assert pre_send_summary["payload"] == rcv_summary["payload"] == pay - assert pre_send_summary["message type"] == rcv_summary["message type"] == test_mtype - assert pre_send_summary["subscription id"] == rcv_summary["subscription id"] == test_subid - - -def test_send_rcv_subid_bad_subid(): - """ - test send and receive where subid is used for routing but nobody recieves this subid - """ - sbuf_send = rmr.rmr_alloc_msg(MRC_SEND, 3, b"\x01\x00\x80", mtype=46656, sub_id=778) - sbuf_send = rmr.rmr_send_msg(MRC_SEND, sbuf_send) - assert rmr.message_summary(sbuf_send)["message state"] == 2 - assert rmr.message_summary(sbuf_send)["message status"] == "RMR_ERR_NOENDPT" - - -def test_send_rcv_subid_bad_mtype(): - """ - test send and receive where subid is used for routing but nobody recieves this mtype - """ - sbuf_send = rmr.rmr_alloc_msg(MRC_SEND, 3, b"\x01\x00\x80", mtype=46657, sub_id=777) - sbuf_send = rmr.rmr_send_msg(MRC_SEND, sbuf_send) - assert rmr.message_summary(sbuf_send)["message state"] == 2 - assert rmr.message_summary(sbuf_send)["message status"] == "RMR_ERR_NOENDPT" - - -def send_burst(mrc, fmt, mtype=1, num=13, counter=0): - """ - Internal function to support test_rcv_all. - Send a burst of messages optionally giving the type, payload - and number to send. - """ - sbuf_send = rmr.rmr_alloc_msg(MRC_SEND, SIZE) # seed message buffer - - for i in range(num): - payload = bytes(fmt % counter, "UTF-8") - counter += 1 - - rmr.set_payload_and_length(payload, sbuf_send) - sbuf_send.contents.mtype = mtype - - max_retries = 5 - while max_retries > 0: - sbuf_send = rmr.rmr_send_msg(mrc, sbuf_send) - ms = rmr.message_summary(sbuf_send) - if ms["message state"] != 10: # 10 is retry - break - max_retries -= 1 - time.sleep(0.75) - - assert ms["message state"] == 0 - assert max_retries > 0 - - -def test_rcv_all(): - """ - test the ability to receive a batch of queued messages. - """ - pay_fmt = "send to ring msg: %d" # dynamic message format with counter - - send_burst(MRC_SEND, pay_fmt) # send a bunch of 13 messages that should queue - time.sleep(1) # ensure underlying transport gets cycles to send/receive - - bundle = helpers.rmr_rcvall_msgs(MRC_BUF_RCV) # use the buffered receiver to read all with a single call - assert len(bundle) == 13 - - for i, ms in enumerate(bundle): - ms = bundle[i] # validate each summary returned, and ordering preserved - assert ms["message state"] == 0 - expected_pay = bytes(pay_fmt % i, "UTF-8") - assert ms["payload"] == expected_pay - - send_burst(MRC_SEND, pay_fmt, mtype=1, num=10) # send a second round with msg types 1 and 2 to test filter - send_burst(MRC_SEND, pay_fmt, mtype=2, num=8) - send_burst(MRC_SEND, pay_fmt, mtype=1, num=5) - send_burst(MRC_SEND, pay_fmt, mtype=2, num=4, counter=8) # total of 12 messages with type 2 should be queued - time.sleep(1) # ensure underlying transport gets cycles to send/receive - - bundle = helpers.rmr_rcvall_msgs_raw(MRC_BUF_RCV, [2]) # receive only message type 2 messages - assert len(bundle) == 12 # we should only get the second batch of 12 messages - - for i, (ms, sbuf) in enumerate(bundle): # test the raw version - test_summary = rmr.message_summary(sbuf) - assert test_summary == ms - assert ms["message state"] == 0 # all should be OK - assert ms["message type"] == 2 # only mtype 2 should have been received - expected_pay = bytes(pay_fmt % i, "UTF-8") # ordering should still jive with the counter - assert ms["payload"] == expected_pay - rmr.rmr_free_msg(sbuf) - - -def test_bad_buffer(): - """test that we get a proper exception when the buffer has a null pointer""" - with pytest.raises(exceptions.BadBufferAllocation): - rmr.rmr_alloc_msg(None, 4096) - - -def test_resize_payload(): - """test the ability to insert a larger payload into an existing message""" - mtype = 99 - subid = 100 - - mbuf = rmr.rmr_alloc_msg(MRC_SEND, 25) # allocate buffer with small payload - mbuf.contents.mtype = mtype # type and sub-id should not change - mbuf.contents.sub_id = subid - - long_payload = b"This is a long payload that should force the message buffer to be reallocated" - rmr.set_payload_and_length(long_payload, mbuf) - summary = rmr.message_summary(mbuf) - assert summary["payload max size"] >= len(long_payload) # RMR may allocate a larger payload space - assert summary["payload length"] == len(long_payload) # however, the length must be exactly the same - assert summary["message type"] == mtype # both mtype and sub-id should be preserved in new - assert summary["subscription id"] == subid diff --git a/src/bindings/rmr-python/tests/test_rmr_mocks.py b/src/bindings/rmr-python/tests/test_rmr_mocks.py deleted file mode 100644 index 7d0cbf0..0000000 --- a/src/bindings/rmr-python/tests/test_rmr_mocks.py +++ /dev/null @@ -1,114 +0,0 @@ -# ================================================================================== -# Copyright (c) 2019 Nokia -# Copyright (c) 2018-2019 AT&T Intellectual Property. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. -# ================================================================================== -import pytest -from rmr import rmr -from rmr.rmr_mocks import rmr_mocks - - -MRC = None -SIZE = 256 - - -def _partial_dict_comparison(subset_dict, target_dict): - """ - Compares that target_dict[k] == subset_dict[k] for all k <- subset_dict - """ - for k, v in subset_dict.items(): - assert k in target_dict - assert target_dict[k] == subset_dict[k] - - -def test_send_mock(monkeypatch): - """ - tests the send mock - """ - monkeypatch.setattr("rmr.rmr.rmr_send_msg", rmr_mocks.send_mock_generator(12)) - rmr_mocks.patch_rmr(monkeypatch) - sbuf = rmr.rmr_alloc_msg(MRC, SIZE) - rmr.set_payload_and_length("testttt".encode("utf8"), sbuf) - - expected = { - "meid": None, - "message source": "localtest:80", - "message state": 0, - "message type": 0, - "message status": "RMR_OK", - "payload": b"testttt", - "payload length": 7, - "payload max size": 4096, - "subscription id": 0, - } - _partial_dict_comparison(expected, rmr.message_summary(sbuf)) - - # set the mtype - sbuf.contents.mtype = 666 - - # send it (the fake send sets the state, and touches nothing else) - sbuf = rmr.rmr_send_msg(MRC, sbuf) - - expected = { - "meid": None, - "message source": "localtest:80", - "message state": 12, - "message type": 666, - "message status": "RMR_ERR_TIMEOUT", - "payload": None, - "payload length": 7, - "payload max size": 4096, - "subscription id": 0, - } - _partial_dict_comparison(expected, rmr.message_summary(sbuf)) - - -def test_rcv_mock(monkeypatch): - """ - tests the rmr recieve mocking generator - """ - rmr_mocks.patch_rmr(monkeypatch) - sbuf = rmr.rmr_alloc_msg(MRC, SIZE) - - # test rcv - monkeypatch.setattr("rmr.rmr.rmr_rcv_msg", rmr_mocks.rcv_mock_generator({"foo": "bar"}, 666, 0, True)) - sbuf = rmr.rmr_rcv_msg(MRC, sbuf) - assert rmr.get_payload(sbuf) == b'{"foo": "bar"}' - assert sbuf.contents.mtype == 666 - assert sbuf.contents.state == 0 - assert sbuf.contents.len == 14 - - # test torcv, although the timeout portion is not currently mocked or tested - monkeypatch.setattr("rmr.rmr.rmr_torcv_msg", rmr_mocks.rcv_mock_generator({"foo": "bar"}, 666, 0, True, 50)) - sbuf = rmr.rmr_torcv_msg(MRC, sbuf, 5) - assert rmr.get_payload(sbuf) == b'{"foo": "bar"}' - assert sbuf.contents.mtype == 666 - assert sbuf.contents.state == 0 - assert sbuf.contents.len == 14 - - -def test_alloc(monkeypatch): - """ - test alloc with all fields set - """ - rmr_mocks.patch_rmr(monkeypatch) - sbuf = rmr.rmr_alloc_msg( - MRC, SIZE, payload=b"foo", gen_transaction_id=True, mtype=5, meid=b"mee", sub_id=234, fixed_transaction_id=b"t" * 32 - ) - summary = rmr.message_summary(sbuf) - assert summary["payload"] == b"foo" - assert summary["transaction id"] == b"t" * 32 - assert summary["message type"] == 5 - assert summary["meid"] == b"mee" - assert summary["subscription id"] == 234 diff --git a/src/bindings/rmr-python/tox.ini b/src/bindings/rmr-python/tox.ini deleted file mode 100644 index 1aec1b2..0000000 --- a/src/bindings/rmr-python/tox.ini +++ /dev/null @@ -1,42 +0,0 @@ -# ================================================================================== -# Copyright (c) 2020 Nokia -# Copyright (c) 2018-2020 AT&T Intellectual Property. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. -# ================================================================================== -[tox] -envlist = py37,py38,flake8 - -[testenv] -deps= - pytest - coverage - pytest-cov -setenv = - LD_LIBRARY_PATH = /usr/local/lib/:/usr/local/lib64 - RMR_SEED_RT = tests/fixtures/test_local.rt - RMR_ASYNC_CONN = 0 - -commands= - pytest --verbose --cov {envsitepackagesdir}/rmr --cov-report xml --cov-report term-missing --cov-report html - coverage xml -i - -[testenv:flake8] -basepython = python3.7 -skip_install = true -deps = flake8 -commands = flake8 setup.py rmr -# tests - -[flake8] -ignore = E501 -- 2.16.6