# HG changeset patch
# User Vyacheslav Savchenko <25712100+SeyfSV@users.noreply.github.com>
# Date 1595932133 -10800
#      Tue Jul 28 13:28:53 2020 +0300
# Node ID 29d4f91c8f23c184c5fa1d8a4a9bfedf193bb84a
# Parent  9eec9adb34798e7490b853de1925a67ff3f61c33
GH #219 Added unpack for CFSF, CFBF and CFIF

diff --git a/code/pymqi/__init__.py b/code/pymqi/__init__.py
--- a/code/pymqi/__init__.py
+++ b/code/pymqi/__init__.py
@@ -2986,6 +2986,24 @@
                     parameter = CFBS(StringLength=parameter.StringLength)
                     parameter.unpack(message[cursor:cursor + parameter.StrucLength])
                 value = parameter.String
+            elif parameter_type == CMQCFC.MQCFT_STRING_FILTER:
+                parameter = CFSF()
+                parameter.unpack(message[cursor:cursor + CMQCFC.MQCFSF_STRUC_LENGTH_FIXED])
+                if parameter.FilterValueLength > 0:
+                    parameter = CFSF(FilterValueLength=parameter.FilterValueLength)
+                    parameter.unpack(message[cursor:cursor + CMQCFC.MQCFSF_STRUC_LENGTH_FIXED + parameter.FilterValueLength])
+                value = (parameter.Operator, parameter.FilterValue)
+            elif parameter_type == CMQCFC.MQCFT_BYTE_STRING_FILTER:
+                parameter = CFBF()
+                parameter.unpack(message[cursor:cursor + CMQCFC.MQCFBF_STRUC_LENGTH_FIXED])
+                if parameter.FilterValueLength > 0:
+                    parameter = CFBF(FilterValueLength=parameter.FilterValueLength)
+                    parameter.unpack(message[cursor:cursor + CMQCFC.MQCFBF_STRUC_LENGTH_FIXED + parameter.FilterValueLength])
+                value = (parameter.Operator, parameter.FilterValue)
+            elif parameter_type == CMQCFC.MQCFT_INTEGER_FILTER:
+                parameter = CFIF()
+                parameter.unpack(message[cursor:cursor + CMQCFC.MQCFIF_STRUC_LENGTH])
+                value = (parameter.Operator, parameter.FilterValue)
             else:
                 pcf_type = struct.unpack(MQLONG_TYPE, message[cursor:cursor + 4])
                 raise NotImplementedError('Unpack for type ({}) not implemented'.format(pcf_type))
diff --git a/code/tests/messages/pcf_with_cfif.dat b/code/tests/messages/pcf_with_cfif.dat
new file mode 100644
index 0000000000000000000000000000000000000000..3cb8714fa57da95f20cae85d74559e4c50d647f7
GIT binary patch
literal 284
zc$|gLu?_)I6olb#U2Fu2LZP#TN+t0Ggi;~Afz}q@SR)dxS|TUAE8CgmH0RDgXKs!K
z5-!N<f$M+{rkG$er>mL*k0I;C2<5FT8bwz4->J$9{|?XEzrx{o-k;7t<gc2{Ph#Ba
kv~6{o;htCB<L)x+XAKwr*fnhIg9-I&_LZvt##`ik0maZ1K>z>%

diff --git a/code/tests/messages/pcf_with_cfsf.dat b/code/tests/messages/pcf_with_cfsf.dat
new file mode 100644
index 0000000000000000000000000000000000000000..287e01b35bcfc99ffba3affeebd56f5efcb0f2ca
GIT binary patch
literal 296
zc$|gLy=nqs5QX7q^Jy0G2MHGGv`A$ocm;}<78373>|!B$yMj#+Y^?<u_S;~W0|UeG
z&Y3eMzL2m*kt_7m;td1zF&olQ)d;_Bril*rhyAElcm;n?l~?c!Tr)qxYQ0&0Z~j*P
zRqgpmbYC*fUow5-QdZgH?zng_>b>A&*2~$?B_H|ECQiHKX`K7;xuxp&;KK6>5>Xfp

diff --git a/code/tests/test_base_api.py b/code/tests/test_base_api.py
--- a/code/tests/test_base_api.py
+++ b/code/tests/test_base_api.py
@@ -312,17 +312,6 @@
         self.assertEqual(md.Format, pymqi.CMQC.MQFMT_STRING)
         self.assertEqual(md.CodedCharSetId, 1208)
 
-    def test_put1_bytes(self):
-        md = pymqi.MD()
-        self.qmgr.put1(self.queue_name, b'\xd1\x82\xd0\xb5\xd1\x81\xd1\x82', md)  # Non-ascii characters
-
-        gmo = pymqi.GMO()
-        gmo.Options = gmo.Options & ~ pymqi.CMQC.MQGMO_CONVERT
-        message = self.queue.get(None, md, gmo)
-
-        self.assertEqual(message, b'\xd1\x82\xd0\xb5\xd1\x81\xd1\x82')
-        self.assertEqual(md.Format, pymqi.CMQC.MQFMT_NONE)
-
     def test_put1(self):
         input_msg = b'Hello world!'
         self.qmgr.put1(self.queue_name, input_msg)
diff --git a/code/tests/test_pcf.py b/code/tests/test_pcf.py
--- a/code/tests/test_pcf.py
+++ b/code/tests/test_pcf.py
@@ -1,10 +1,16 @@
 """Test PCF usage."""
 import os
+from sys import version_info as sys_version_info
+
 from unittest import skip
 from unittest import skipIf
-from ddt import data
+from ddt import data  # type: ignore
 from ddt import ddt
-from sys import version_info as sys_version_info
+
+try:
+    from typing import List
+except ImportError:
+    pass
 
 from test_setup import Tests  # noqa
 from test_setup import main  # noqa
@@ -15,7 +21,6 @@
 class TestPCF(Tests):
     """Class for MQ PCF testing."""
 
-    pcf = None
     messages_dir = os.path.join(os.path.dirname(__file__), "messages")
 
     @classmethod
@@ -44,7 +49,7 @@
 
         super(TestPCF, self).tearDown()
 
-    @skip('Not implemented')
+    @skip('Test not implemented')
     def test_mqcfbf(self):
         """Test MQCFBF PCF byte string filter parameter."""
 
@@ -53,7 +58,7 @@
 
         Also uses MQCFIN and MQCFIL as parameters
         """
-        attrs = []
+        attrs = []  # type: List[pymqi.MQOpts]
         attrs.append(pymqi.CFBS(Parameter=pymqi.CMQCFC.MQBACF_GENERIC_CONNECTION_ID,
                                 String=b''))
         attrs.append(pymqi.CFIN(Parameter=pymqi.CMQCFC.MQIACF_CONN_INFO_TYPE,
@@ -76,7 +81,7 @@
 
         Also uses MQCFST, MQCFIN and MQCFIL as parameters
         """
-        attrs = []
+        attrs = []  # type: List[pymqi.MQOpts]
         attrs.append(pymqi.CFST(Parameter=pymqi.CMQC.MQCA_Q_NAME,
                                 String=b'*'))
         attrs.append(pymqi.CFIN(Parameter=pymqi.CMQC.MQIA_Q_TYPE,
@@ -101,7 +106,7 @@
 
         Also uses MQCFST, MQCFIN and MQCFIL as parameters
         """
-        attrs = []
+        attrs = []  # type: List[pymqi.MQOpts]
         attrs.append(pymqi.CFST(Parameter=pymqi.CMQC.MQCA_Q_NAME,
                                 String=b'*'))
         attrs.append(pymqi.CFIN(Parameter=pymqi.CMQC.MQIA_Q_TYPE,
@@ -130,7 +135,7 @@
 
         Also uses MQCFST and MQCFIN as parameters
         """
-        attrs = []
+        attrs = []  # type: List[pymqi.MQOpts]
         attrs.append(pymqi.CFST(Parameter=pymqi.CMQC.MQCA_NAMELIST_NAME,
                                 String='{}NAMELIST'.format(self.prefix).encode()))
         attrs.append(pymqi.CFSL(Parameter=pymqi.CMQC.MQCA_NAMES,
@@ -187,14 +192,14 @@
         get_md = pymqi.MD(MsgId=put_md.MsgId)  # pylint: disable=no-member
         message = queue.get(None, get_md, get_opts)
         queue.close()
-        message = pymqi.PCFExecute.unpack(message)
+        unpacked_message = pymqi.PCFExecute.unpack(message)
 
-        self.assertTrue(isinstance(message[0][1], list),
-                        'Returned value is not list: {}'.format(type(message[0][1])))
+        self.assertTrue(isinstance(unpacked_message[0][1], list),
+                        'Returned value is not list: {}'.format(type(unpacked_message[0][1])))
 
-        self.assertTrue(len(message[0][1]) == len(value), 'List length is different!')
+        self.assertTrue(len(unpacked_message[0][1]) == len(value), 'List length is different!')
 
-        for item in message[0][1]:
+        for item in unpacked_message[0][1]:
             self.assertTrue(item in value, '{} value not in values list'.format(item))
             value.remove(item)
 
@@ -204,25 +209,25 @@
                             Type=pymqi.CMQCFC.MQCFT_USER,
                             ParameterCount=4).pack()
         message += pymqi.CFST(Parameter=pymqi.CMQC.MQCA_Q_MGR_NAME,
-                                    String=b'QM1').pack()
+                              String=b'QM1').pack()
         # group1
         message += pymqi.CFGR(Parameter=pymqi.CMQCFC.MQGACF_Q_STATISTICS_DATA,
-                                    ParameterCount=3).pack()
+                              ParameterCount=3).pack()
         message += pymqi.CFST(Parameter=pymqi.CMQC.MQCA_Q_NAME,
-                                    String=b'SYSTEM.ADMIN.COMMAND.QUEUE').pack()
+                              String=b'SYSTEM.ADMIN.COMMAND.QUEUE').pack()
         message += pymqi.CFIN64(Parameter=pymqi.CMQCFC.MQIAMO_Q_MIN_DEPTH,
-                                    Value=10).pack()
+                                Value=10).pack()
         message += pymqi.CFIL64(Parameter=pymqi.CMQCFC.MQIAMO64_AVG_Q_TIME,
-                                    Values=[1, 2, 3]).pack()
+                                Values=[1, 2, 3]).pack()
         # group2
         message += pymqi.CFGR(Parameter=pymqi.CMQCFC.MQGACF_Q_STATISTICS_DATA,
-                                    ParameterCount=3).pack()
+                              ParameterCount=3).pack()
         message += pymqi.CFST(Parameter=pymqi.CMQC.MQCA_Q_NAME,
-                                    String=b'SYSTEM.ADMIN.COMMAND.QUEUE2').pack()
+                              String=b'SYSTEM.ADMIN.COMMAND.QUEUE2').pack()
         message += pymqi.CFIN64(Parameter=pymqi.CMQCFC.MQIAMO_Q_MIN_DEPTH,
-                                    Value=20).pack()
+                                Value=20).pack()
         message += pymqi.CFIL64(Parameter=pymqi.CMQCFC.MQIAMO64_AVG_Q_TIME,
-                                    Values=[111, 222]).pack()
+                                Values=[111, 222]).pack()
 
         message += pymqi.CFST(Parameter=pymqi.CMQCFC.MQCAMO_START_TIME,
                               String=b'10.41.58').pack()
@@ -266,7 +271,7 @@
                             Command=pymqi.CMQCFC.MQCMD_STATISTICS_Q,
                             ParameterCount=1).pack()
         message += pymqi.CFST(Parameter=pymqi.CMQC.MQCA_Q_MGR_NAME,
-                                    String=b'QM1').pack()
+                              String=b'QM1').pack()
 
         queue = pymqi.Queue(self.qmgr, self.queue_name,
                             pymqi.CMQC.MQOO_INPUT_AS_Q_DEF + pymqi.CMQC.MQOO_OUTPUT)
@@ -283,8 +288,8 @@
         queue.close()
         message, header = pymqi.PCFExecute.unpack(message)
 
-        self.assertEqual(header.Command,  pymqi.CMQCFC.MQCMD_STATISTICS_Q)
-        self.assertEqual(header.Type,  pymqi.CMQCFC.MQCFT_STATISTICS)
+        self.assertEqual(header.Command, pymqi.CMQCFC.MQCMD_STATISTICS_Q)  # pylint: disable=no-member
+        self.assertEqual(header.Type, pymqi.CMQCFC.MQCFT_STATISTICS)  # pylint: disable=no-member
 
         self.assertEqual({
             pymqi.CMQC.MQCA_Q_MGR_NAME: b'QM1\x00',
@@ -292,22 +297,52 @@
 
     def test_unpack_group(self):
         """Test parameters group unpack."""
-        binary_message = open(os.path.join(self.messages_dir, "statistics_q.dat"), "rb").read()
+        with open(os.path.join(self.messages_dir, "statistics_q.dat"), "rb") as file:
+            binary_message = file.read()
+            message, header = pymqi.PCFExecute.unpack(binary_message)
+
+            self.assertEqual(header.Command, pymqi.CMQCFC.MQCMD_STATISTICS_Q)  # pylint: disable=no-member
+            self.assertEqual(header.Type, pymqi.CMQCFC.MQCFT_STATISTICS)  # pylint: disable=no-member
+
+            self.assertEqual(message[pymqi.CMQC.MQCA_Q_MGR_NAME].strip(), b'mq_mgr1')
+            self.assertEqual(message[pymqi.CMQCFC.MQCAMO_START_DATE], b'2020-06-15\x00\x00')
+            self.assertEqual(len(message[pymqi.CMQCFC.MQGACF_Q_STATISTICS_DATA]), 16)
 
-        message, header = pymqi.PCFExecute.unpack(binary_message)
+            item = message[pymqi.CMQCFC.MQGACF_Q_STATISTICS_DATA][0]
+            self.assertEqual(item[pymqi.CMQC.MQCA_Q_NAME].strip(), b'SYSTEM.ADMIN.COMMAND.QUEUE')
+            self.assertEqual(item[pymqi.CMQCFC.MQIAMO_PUTS], [14, 0])
 
-        self.assertEqual(header.Command,  pymqi.CMQCFC.MQCMD_STATISTICS_Q)
-        self.assertEqual(header.Type,  pymqi.CMQCFC.MQCFT_STATISTICS)
+    def test_unpack_cfsf(self):
+        """Test unpack of PCF message with MQCFSF structure."""
+        with open(os.path.join(self.messages_dir, "pcf_with_cfsf.dat"), "rb") as file:
+            binary_message = file.read()
+
+            message, _ = pymqi.PCFExecute.unpack(binary_message)
 
-        self.assertEqual(message[pymqi.CMQC.MQCA_Q_MGR_NAME].strip(), b'mq_mgr1')
-        self.assertEqual(message[pymqi.CMQCFC.MQCAMO_START_DATE], b'2020-06-15\x00\x00')
-        self.assertEqual(len(message[pymqi.CMQCFC.MQGACF_Q_STATISTICS_DATA]), 16)
+        self.assertEqual(message.get(pymqi.CMQCFC.MQGACF_COMMAND_DATA, [{}])[0].get(pymqi.CMQC.MQCA_Q_DESC)[0],
+                         pymqi.CMQCFC.MQCFOP_LIKE)
+
+        self.assertEqual(message.get(pymqi.CMQCFC.MQGACF_COMMAND_DATA,
+                                     [{}])[0].get(pymqi.CMQC.MQCA_Q_DESC)[1].rstrip(b'\x00'),
+                         b'test*')
+
+    @skip('Test not implemented')
+    def test_unpack_cfbf(self):
+        """Test unpack of PCF message with MQCFBF structure."""
+
 
-        item = message[pymqi.CMQCFC.MQGACF_Q_STATISTICS_DATA][0]
-        self.assertEqual(item[pymqi.CMQC.MQCA_Q_NAME].strip(), b'SYSTEM.ADMIN.COMMAND.QUEUE')
-        self.assertEqual(item[pymqi.CMQCFC.MQIAMO_PUTS], [14, 0])
+    def test_unpack_cfif(self):
+        """Test unpack of PCF message with MQCFIF structure."""
+        with open(os.path.join(self.messages_dir, "pcf_with_cfif.dat"), "rb") as file:
+            binary_message = file.read()
 
-    @skipIf(sys_version_info < (3, 7),'Python pre 3.7 issues: https://github.com/dsuch/pymqi/issues/207#issuecomment-645422229')
+            message, _ = pymqi.PCFExecute.unpack(binary_message)
+
+        self.assertEqual(message.get(pymqi.CMQCFC.MQGACF_COMMAND_DATA, [{}])[0].get(pymqi.CMQC.MQIA_CURRENT_Q_DEPTH),
+                         (pymqi.CMQCFC.MQCFOP_GREATER, 0))
+
+    @skipIf(sys_version_info < (3, 7),
+            'Python pre 3.7 issues: https://github.com/dsuch/pymqi/issues/207#issuecomment-645422229')
     def test_mqcfbs_old(self):
         """Test byte string MQCFBS with old style."""
         attrs = {
@@ -317,7 +352,7 @@
         }
         fltr = pymqi.Filter(pymqi.CMQC.MQIA_APPL_TYPE).equal(pymqi.CMQC.MQAT_USER)
 
-        results = self.pcf.MQCMD_INQUIRE_CONNECTION(attrs) #, [fltr])
+        results = self.pcf.MQCMD_INQUIRE_CONNECTION(attrs, [fltr])
 
         self.assertGreater(len(results), 0)
 
diff --git a/code/tests/test_setup.py b/code/tests/test_setup.py
--- a/code/tests/test_setup.py
+++ b/code/tests/test_setup.py
@@ -23,7 +23,8 @@
 
     prefix = ''
 
-    qmgr = None
+    qmgr = None  # type: pymqi.QueueManager
+    pcf = None  # type: pymqi.PCFExecute
 
 
     @classmethod