Add subscription id setting/testing

Issue-ID: RICPLT-2630
Change-Id: Ia89ba3af2647b0e41538112cda7715aa4be77a7b
Signed-off-by: Tommy Carpenter <tc677g@att.com>
diff --git a/src/bindings/rmr-python/docs/Changelog.rst b/src/bindings/rmr-python/docs/release-notes.rst
similarity index 97%
rename from src/bindings/rmr-python/docs/Changelog.rst
rename to src/bindings/rmr-python/docs/release-notes.rst
index 4fa1629..7e31581 100644
--- a/src/bindings/rmr-python/docs/Changelog.rst
+++ b/src/bindings/rmr-python/docs/release-notes.rst
@@ -7,12 +7,14 @@
 and this project adheres to `Semantic
 Versioning <http://semver.org/>`__.
 
-[X.X.X] - 10/30/2019
+[X.X.X] - xxx
 --------------------
 
 ::
     * 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
diff --git a/src/bindings/rmr-python/rmr/rmr.py b/src/bindings/rmr-python/rmr/rmr.py
index 99c2088..b264cd5 100644
--- a/src/bindings/rmr-python/rmr/rmr.py
+++ b/src/bindings/rmr-python/rmr/rmr.py
@@ -216,7 +216,7 @@
 _rmr_alloc_msg.restype = POINTER(rmr_mbuf_t)
 
 
-def rmr_alloc_msg(vctx, size, payload=None, gen_transaction_id=False, mtype=None, meid=None):
+def rmr_alloc_msg(vctx, size, payload=None, gen_transaction_id=False, mtype=None, meid=None, sub_id=None):
     """
     Refer to the rmr C documentation for rmr_alloc_msg
     extern rmr_mbuf_t* rmr_alloc_msg(void* vctx, int size)
@@ -228,9 +228,11 @@
 
     """
     sbuf = _rmr_alloc_msg(vctx, size)
-    # make sure it's good
     try:
+        # make sure the alloc worked
         sbuf.contents
+
+        # set specified fields
         if payload:
             set_payload_and_length(payload, sbuf)
 
@@ -243,6 +245,9 @@
         if meid:
             rmr_set_meid(sbuf, meid)
 
+        if sub_id:
+            sbuf.contents.sub_id = sub_id
+
         return sbuf
 
     except ValueError:
diff --git a/src/bindings/rmr-python/tests/conftest.py b/src/bindings/rmr-python/tests/conftest.py
index 2634edc..e29c779 100644
--- a/src/bindings/rmr-python/tests/conftest.py
+++ b/src/bindings/rmr-python/tests/conftest.py
@@ -22,7 +22,7 @@
 # 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. 
+# list of what is/could be used by this package.
 @pytest.fixture
 def expected_constants():
     return {
@@ -32,7 +32,7 @@
         "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_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,
diff --git a/src/bindings/rmr-python/tests/fixtures/test_local.rt b/src/bindings/rmr-python/tests/fixtures/test_local.rt
index bf49290..e77afac 100644
--- a/src/bindings/rmr-python/tests/fixtures/test_local.rt
+++ b/src/bindings/rmr-python/tests/fixtures/test_local.rt
@@ -1,6 +1,8 @@
 # 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
index cd07545..50dffc2 100644
--- a/src/bindings/rmr-python/tests/test_rmr.py
+++ b/src/bindings/rmr-python/tests/test_rmr.py
@@ -41,7 +41,7 @@
 
     global MRC_BUF_RCV
     MRC_BUF_RCV = rmr.rmr_init(b"4564", rmr.RMR_MAX_RCV_BYTES, 0x02)
-    while rmr.rmr_ready(MRC_RCV) == 0:
+    while rmr.rmr_ready(MRC_BUF_RCV) == 0:
         time.sleep(1)
 
 
@@ -60,6 +60,7 @@
     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"
@@ -152,6 +153,21 @@
     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_rcv_timeout():
     """
     test torcv; this is a scary test because if it fails... it doesn't fail, it will run forever!
@@ -207,6 +223,54 @@
     assert send_ack_summary["payload"] == ack_pay
 
 
+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.
@@ -276,32 +340,19 @@
         rmr.rmr_alloc_msg(None, 4096)
 
 
-def test_alloc_fancy():
-    """test allocation with setting payload, trans, mtype"""
-    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")
-    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 summary["message state"] == 0
-    assert summary["message type"] == 14
-    assert summary["meid"] == b"asdf"
-
-
 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.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["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