Greatly improve test coverage 70/770/2
authorTommy Carpenter <tommy@research.att.com>
Thu, 22 Aug 2019 13:34:57 +0000 (09:34 -0400)
committerTommy Carpenter <tommy@research.att.com>
Thu, 22 Aug 2019 15:01:04 +0000 (11:01 -0400)
Change-Id: Iaddc5fb3a365b34b91c3ae15649b4bb43f7f69a7
Signed-off-by: Tommy Carpenter <tommy@research.att.com>
src/bindings/rmr-python/docs/Changelog.rst
src/bindings/rmr-python/docs/source/index.rst
src/bindings/rmr-python/rmr/rmr.py
src/bindings/rmr-python/rmr/rmr_mocks/rmr_mocks.py
src/bindings/rmr-python/setup.py
src/bindings/rmr-python/tests/conftest.py
src/bindings/rmr-python/tests/fixtures/test_local.rt [new file with mode: 0644]
src/bindings/rmr-python/tests/test_rmr.py
src/bindings/rmr-python/tox.ini

index 894ce3d..e758354 100644 (file)
@@ -7,6 +7,15 @@ The format is based on `Keep a Changelog <http://keepachangelog.com/>`__
 and this project adheres to `Semantic
 Versioning <http://semver.org/>`__.
 
+[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
 --------------------
 
index 29a6c94..8b354da 100644 (file)
@@ -40,18 +40,23 @@ are not yet implemented in this library (do we need them?):
 
 Unit Testing
 ============
-You can unit test outside of docker, or in docker. Unit testing outside of docker currently requires rmr to be installed.
+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
 
 ::
 
-   tox
-   open htmlcov/index.html
+    docker build -t rmrunittestt:latest -f Dockerfile-Unit-Test   .
+
+A coverage report will be shown in stdout.
 
-Or, use the provided Dockerfile (building is enough):
+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.
 
 ::
 
-    docker build -t rmrunittestt:latest -f Dockerfile-Unit-Test   .
+   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
 ============
index 9d21b88..7e5d493 100644 (file)
@@ -309,6 +309,10 @@ def rmr_bytes2meid(ptr_mbuf, src, length):
     return _rmr_bytes2meid(ptr_mbuf, src, length)
 
 
+# this is an alias to rmr_bytes2meid using familiar set/get terminoloigy
+rmr_set_meid = rmr_bytes2meid
+
+
 # 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.
index 6037e1f..239ac2b 100644 (file)
@@ -34,7 +34,7 @@ def rcv_mock_generator(msg_payload, msg_type, msg_state, jsonb, timeout=0):
         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'
+        if msg_state != 0:  # set something in transport state if 'error'
             sbuf.contents.tp_state = 99
         else:
             sbuf.contents.tp_state = 0
@@ -52,7 +52,7 @@ def send_mock_generator(msg_state):
 
     def f(_unused, sbuf):
         sbuf.contents.state = msg_state
-        if msg_state != 0:                # set something in transport state if 'error'
+        if msg_state != 0:  # set something in transport state if 'error'
             sbuf.contents.tp_state = 99
         else:
             sbuf.contents.tp_state = 0
index 06f4c14..ebdc471 100644 (file)
@@ -32,7 +32,7 @@ def _long_descr():
 
 setup(
     name="rmr",
-    version="0.10.8",
+    version="0.11.0",
     packages=find_packages(),
     author="Tommy Carpenter, E. Scott Daniels",
     description="Python wrapper for RIC RMR",
index 51ddda9..3019352 100644 (file)
 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
 @pytest.fixture
-def fake_consts():
-    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_AUTO_ALLOC": 1,
-            "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}
+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_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"}
+    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
new file mode 100644 (file)
index 0000000..4f09782
--- /dev/null
@@ -0,0 +1,3 @@
+newrt|start
+rte|10001|localhost:4562
+newrt|end
index fdc21ed..f3d0b75 100644 (file)
 #   See the License for the specific language governing permissions and
 #   limitations under the License.
 # ==================================================================================
+import time
 import pytest
-import json
 from rmr import rmr
-from rmr.rmr_mocks import rmr_mocks
 
 
-MRC = None
 SIZE = 256
+MRC = None
+
+
+def setup_module():
+    global MRC
+    MRC = rmr.rmr_init(b"4562", rmr.RMR_MAX_RCV_BYTES, 0x00)
+    while rmr.rmr_ready(MRC) == 0:
+        time.sleep(1)
 
 
-def test_get_mapping_dict(monkeypatch, fake_consts, expected_states):
+def teardown_module():
+    rmr.rmr_close(MRC)
+
+
+def _assert_new_sbuf(sbuf):
     """
-    test getting mapping string
+    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["transaction id"] == b""
+    assert summary["message state"] == 0
+    assert summary["message status"] == "RMR_OK"
+    assert summary["meid"] is None
+    assert summary["errno"] == 0
 
-    def fake_rmr_get_consts():
-        return json.dumps(fake_consts).encode("utf-8")
 
-    monkeypatch.setattr("rmr.rmr._rmr_const", fake_rmr_get_consts)
-    assert rmr._get_mapping_dict() == expected_states
-    # do again, trigger cache line coverage
-    assert rmr._get_mapping_dict() == expected_states
+def test_get_constants(expected_constants):
+    """
+    test getting constants
+    """
+    assert rmr._get_constants() == expected_constants
+
 
+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_prettify(monkeypatch):
-    rmr_mocks.patch_rmr(monkeypatch)
-
-    # here we re-monkey get_meid
-    monkeypatch.setattr("rmr.rmr.get_meid", lambda _: "yoooo")
+def test_meid_prettify():
+    """
+    test the printing of meid based on it's value
+    """
+    # TODO?? weirdness: setting it takes bytes, but getting it returns a string. This does NOT happen for payload; bytes in, bytes come out.
     sbuf = rmr.rmr_alloc_msg(MRC, SIZE)
+    rmr.rmr_set_meid(sbuf, b"\x00" * 32, 32)
     summary = rmr.message_summary(sbuf)
-    assert summary["meid"] == "yoooo"
+    assert summary["meid"] is None  # summary does a pretty print" of 32 null bytes
+    assert rmr.get_meid(sbuf) == "\x00" * 32  # real underlying value
+
 
-    # test bytes
-    monkeypatch.setattr("rmr.rmr.get_meid", lambda _: b"\x01\x00f\x80")
+def test_rmr_set_get():
+    """
+    test set functions
+    """
     sbuf = rmr.rmr_alloc_msg(MRC, 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["meid"] == b"\x01\x00f\x80"
+    assert summary["payload"] == pay
+    assert summary["payload length"] == 3
 
-    # test the cleanup of null bytes
-    monkeypatch.setattr(
-        "rmr.rmr.get_meid",
-        lambda _: "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00",
-    )
-    sbuf = rmr.rmr_alloc_msg(MRC, SIZE)
+    # 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.get_meid(sbuf) == "\x00" * 32
+    assert summary["meid"] is None  # the summary printing function shows the above horridness as None
+    rmr.rmr_set_meid(sbuf, b"666", 3)
     summary = rmr.message_summary(sbuf)
-    assert summary["meid"] == None
+    # TODO?? weirdness: setting it takes bytes, but getting it returns a string. This does NOT happen for payload; bytes in, bytes come out.
+    assert rmr.get_meid(sbuf) == summary["meid"] == "666" + "\x00" * 29
index cb7cf77..f67ca14 100644 (file)
@@ -22,8 +22,12 @@ deps=
     pytest
     coverage
     pytest-cov
-setenv = LD_LIBRARY_PATH = /usr/local/lib/:/usr/local/lib64
-commands=pytest --verbose --cov {envsitepackagesdir}/rmr  --cov-report term-missing
+setenv =
+    LD_LIBRARY_PATH = /usr/local/lib/:/usr/local/lib64
+    RMR_SEED_RT = tests/fixtures/test_local.rt
+
+
+commands=pytest --verbose --cov {envsitepackagesdir}/rmr  --cov-report term-missing --cov-report html
 
 [testenv:flake8]
 basepython = python3.7