robotframework-ibmmq 0.1.2__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,172 @@
1
+ Metadata-Version: 2.4
2
+ Name: robotframework-ibmmq
3
+ Version: 0.1.2
4
+ Summary: A Robotframework library for IBM MQ
5
+ Keywords: robotframework,ibm,mqlibrary
6
+ Author: Niels Janssen
7
+ Author-email: Niels Janssen <niels.janssen@uwv.nl>
8
+ License-Expression: EUPL-1.2
9
+ Classifier: Development Status :: 3 - Alpha
10
+ Classifier: Intended Audience :: Developers
11
+ Classifier: Topic :: Software Development :: Testing
12
+ Classifier: Framework :: Robot Framework
13
+ Classifier: Framework :: Robot Framework :: Library
14
+ Classifier: Programming Language :: Python :: 3
15
+ Classifier: Operating System :: OS Independent
16
+ Requires-Dist: robotframework>=7.3.0,<8.3.0
17
+ Requires-Dist: ibmmq>=2.0.0,<3.0.0
18
+ Requires-Dist: twine ; extra == 'deploy'
19
+ Requires-Dist: build ; extra == 'deploy'
20
+ Requires-Dist: wheel ; extra == 'deploy'
21
+ Maintainer: Niels Janssen
22
+ Maintainer-email: Niels Janssen <niels.janssen@uwv.nl>
23
+ Requires-Python: >=3.9.0
24
+ Project-URL: Homepage, https://github.com/nluwv/robotframework-ibmmq
25
+ Project-URL: Documentation, https://robotframework-ibmmq.netlify.app/IBMMQLibrary.html
26
+ Project-URL: Repository, https://github.com/nluwv/robotframework-ibmmq.git
27
+ Project-URL: Issues, https://github.com/nluwv/robotframework-ibmmq/issues
28
+ Provides-Extra: deploy
29
+ Description-Content-Type: text/markdown
30
+
31
+ # robotframework-ibmmq
32
+
33
+ **Robot Framework keywords for IBM MQ — powered by the `ibmmq` Python package.**
34
+
35
+ This library is a **thin, explicit Robot Framework wrapper around the `ibmmq` Python package**.
36
+ It does **not** abstract away IBM MQ complexity — and that is **by design**.
37
+
38
+ If you use this library, you are using **real IBM MQ**, with **real native dependencies**, exactly like production.
39
+
40
+ ---
41
+
42
+ ## What this library is (and is not)
43
+
44
+ ✅ **IS**
45
+ - A Robot Framework library for **connecting to IBM MQ**
46
+ - A wrapper around the **`ibmmq` Python package**
47
+ - Designed for **real integration testing**, not mocks or file-based substitutes
48
+
49
+ ❌ **IS NOT**
50
+ - A pure-Python library
51
+ - A “just pip install and go” solution
52
+ - A fake or simulated MQ implementation
53
+
54
+ If you are looking for something that avoids native dependencies, **this library is not for you**.
55
+
56
+ ---
57
+
58
+ ## 🚨 Read this first: IBM MQ prerequisites are mandatory
59
+
60
+ This library **directly depends on `ibmmq`**, which is a **Python extension module backed by IBM MQ native libraries**.
61
+
62
+ > **If `ibmmq` does not work on your machine, this Robot Framework library will not work either.**
63
+
64
+ Before you do *anything else*, you **must** read and follow the official `ibmmq` prerequisites:
65
+
66
+ 👉 **Official ibmmq prerequisites (REQUIRED):**
67
+ https://github.com/ibm-messaging/mq-mqi-python?tab=readme-ov-file#prerequisites
68
+
69
+ ### In practical terms, this means:
70
+
71
+ You **must have**, on the machine where tests run:
72
+
73
+ - ✅ IBM MQ C Client
74
+ - ✅ IBM MQ SDK
75
+ - ✅ A working C/C++ build toolchain
76
+ - ✅ Correct environment variables (e.g. `MQ_FILE_PATH` if MQ is not installed in the default location)
77
+
78
+ If any of the above is missing, you will see errors such as:
79
+
80
+ - `ModuleNotFoundError: No module named 'ibmmqc'`
81
+ - DLL load failures
82
+ - Import errors during `pip install` or at runtime
83
+
84
+ These are **environment issues**, not bugs in this library.
85
+
86
+ ---
87
+
88
+ ## Platform notes
89
+
90
+ - ✅ Windows: Supported
91
+ - ✅ Linux: Supported
92
+ - ❌ No native MQ installation = no support
93
+
94
+ On Windows, a proper **Visual C++ build environment is required**, because `ibmmq` includes native extensions.
95
+
96
+ ---
97
+
98
+ ## Installation
99
+
100
+ ### Step 1 — Verify `ibmmq` works first (strongly recommended)
101
+
102
+ ```bash
103
+ python -c "import ibmmq; print('ibmmq OK')"
104
+ ```
105
+
106
+ If this fails, **stop here** and fix your IBM MQ / `ibmmq` installation first.
107
+
108
+ ### Step 2 — Install this library
109
+
110
+ ```bash
111
+ pip install robotframework-ibmmq
112
+ ```
113
+
114
+ No magic. No hidden installers.
115
+
116
+ ---
117
+
118
+ ## Usage example
119
+
120
+ ```robot
121
+ *** Settings ***
122
+ Library MQLibrary
123
+
124
+ *** Test Cases ***
125
+ Connect to IBM MQ
126
+ Connect MQ
127
+ ... queue_manager=QM_EXAMPLE
128
+ ... hostname=mq.example.internal
129
+ ... port=1414
130
+ ... channel=SYSTEM.ADMIN.SVRCONN
131
+ ... username=${NONE}
132
+ ... password=${NONE}
133
+
134
+ Disconnect All MQ Connections
135
+ ```
136
+
137
+ This connects to a **real queue manager** using a **real MQ channel**.
138
+
139
+ ---
140
+
141
+ ## MQ administration notes
142
+
143
+ If required:
144
+
145
+ - Ensure the MQ channel exists and is running
146
+ - Ensure the MQ listener is active
147
+ - Common admin channel: `SYSTEM.ADMIN.SVRCONN`
148
+
149
+ Use **IBM MQ Explorer** or platform tooling to manage this.
150
+
151
+ ---
152
+
153
+ ## Troubleshooting
154
+
155
+ Errors mentioning `ibmmqc`, DLL load failures, or missing shared libraries are **IBM MQ / ibmmq environment problems**.
156
+
157
+ Re-check:
158
+ - IBM MQ installation
159
+ - `ibmmq` prerequisites
160
+ - Environment variables
161
+ - 32-bit vs 64-bit mismatches
162
+
163
+ Official reference:
164
+ https://github.com/ibm-messaging/mq-mqi-python?tab=readme-ov-file#prerequisites
165
+
166
+ ---
167
+
168
+ ## Acknowledgements ❤️
169
+
170
+ **Special thanks to UWV** for sponsoring, supporting, and **open-sourcing** this library.
171
+
172
+ By funding real-world test tooling and releasing it as open source, UWV has contributed back to the broader Robot Framework and IBM MQ communities.
@@ -0,0 +1,142 @@
1
+ # robotframework-ibmmq
2
+
3
+ **Robot Framework keywords for IBM MQ — powered by the `ibmmq` Python package.**
4
+
5
+ This library is a **thin, explicit Robot Framework wrapper around the `ibmmq` Python package**.
6
+ It does **not** abstract away IBM MQ complexity — and that is **by design**.
7
+
8
+ If you use this library, you are using **real IBM MQ**, with **real native dependencies**, exactly like production.
9
+
10
+ ---
11
+
12
+ ## What this library is (and is not)
13
+
14
+ ✅ **IS**
15
+ - A Robot Framework library for **connecting to IBM MQ**
16
+ - A wrapper around the **`ibmmq` Python package**
17
+ - Designed for **real integration testing**, not mocks or file-based substitutes
18
+
19
+ ❌ **IS NOT**
20
+ - A pure-Python library
21
+ - A “just pip install and go” solution
22
+ - A fake or simulated MQ implementation
23
+
24
+ If you are looking for something that avoids native dependencies, **this library is not for you**.
25
+
26
+ ---
27
+
28
+ ## 🚨 Read this first: IBM MQ prerequisites are mandatory
29
+
30
+ This library **directly depends on `ibmmq`**, which is a **Python extension module backed by IBM MQ native libraries**.
31
+
32
+ > **If `ibmmq` does not work on your machine, this Robot Framework library will not work either.**
33
+
34
+ Before you do *anything else*, you **must** read and follow the official `ibmmq` prerequisites:
35
+
36
+ 👉 **Official ibmmq prerequisites (REQUIRED):**
37
+ https://github.com/ibm-messaging/mq-mqi-python?tab=readme-ov-file#prerequisites
38
+
39
+ ### In practical terms, this means:
40
+
41
+ You **must have**, on the machine where tests run:
42
+
43
+ - ✅ IBM MQ C Client
44
+ - ✅ IBM MQ SDK
45
+ - ✅ A working C/C++ build toolchain
46
+ - ✅ Correct environment variables (e.g. `MQ_FILE_PATH` if MQ is not installed in the default location)
47
+
48
+ If any of the above is missing, you will see errors such as:
49
+
50
+ - `ModuleNotFoundError: No module named 'ibmmqc'`
51
+ - DLL load failures
52
+ - Import errors during `pip install` or at runtime
53
+
54
+ These are **environment issues**, not bugs in this library.
55
+
56
+ ---
57
+
58
+ ## Platform notes
59
+
60
+ - ✅ Windows: Supported
61
+ - ✅ Linux: Supported
62
+ - ❌ No native MQ installation = no support
63
+
64
+ On Windows, a proper **Visual C++ build environment is required**, because `ibmmq` includes native extensions.
65
+
66
+ ---
67
+
68
+ ## Installation
69
+
70
+ ### Step 1 — Verify `ibmmq` works first (strongly recommended)
71
+
72
+ ```bash
73
+ python -c "import ibmmq; print('ibmmq OK')"
74
+ ```
75
+
76
+ If this fails, **stop here** and fix your IBM MQ / `ibmmq` installation first.
77
+
78
+ ### Step 2 — Install this library
79
+
80
+ ```bash
81
+ pip install robotframework-ibmmq
82
+ ```
83
+
84
+ No magic. No hidden installers.
85
+
86
+ ---
87
+
88
+ ## Usage example
89
+
90
+ ```robot
91
+ *** Settings ***
92
+ Library MQLibrary
93
+
94
+ *** Test Cases ***
95
+ Connect to IBM MQ
96
+ Connect MQ
97
+ ... queue_manager=QM_EXAMPLE
98
+ ... hostname=mq.example.internal
99
+ ... port=1414
100
+ ... channel=SYSTEM.ADMIN.SVRCONN
101
+ ... username=${NONE}
102
+ ... password=${NONE}
103
+
104
+ Disconnect All MQ Connections
105
+ ```
106
+
107
+ This connects to a **real queue manager** using a **real MQ channel**.
108
+
109
+ ---
110
+
111
+ ## MQ administration notes
112
+
113
+ If required:
114
+
115
+ - Ensure the MQ channel exists and is running
116
+ - Ensure the MQ listener is active
117
+ - Common admin channel: `SYSTEM.ADMIN.SVRCONN`
118
+
119
+ Use **IBM MQ Explorer** or platform tooling to manage this.
120
+
121
+ ---
122
+
123
+ ## Troubleshooting
124
+
125
+ Errors mentioning `ibmmqc`, DLL load failures, or missing shared libraries are **IBM MQ / ibmmq environment problems**.
126
+
127
+ Re-check:
128
+ - IBM MQ installation
129
+ - `ibmmq` prerequisites
130
+ - Environment variables
131
+ - 32-bit vs 64-bit mismatches
132
+
133
+ Official reference:
134
+ https://github.com/ibm-messaging/mq-mqi-python?tab=readme-ov-file#prerequisites
135
+
136
+ ---
137
+
138
+ ## Acknowledgements ❤️
139
+
140
+ **Special thanks to UWV** for sponsoring, supporting, and **open-sourcing** this library.
141
+
142
+ By funding real-world test tooling and releasing it as open source, UWV has contributed back to the broader Robot Framework and IBM MQ communities.
@@ -0,0 +1,50 @@
1
+ [build-system]
2
+ requires = ["uv_build>=0.10.7,<0.11.0"]
3
+ build-backend = "uv_build"
4
+
5
+
6
+ [project]
7
+ name = "robotframework-ibmmq"
8
+ version = "0.1.2"
9
+ authors = [
10
+ { name="Niels Janssen", email="niels.janssen@uwv.nl" },
11
+ ]
12
+ maintainers = [
13
+ { name="Niels Janssen", email="niels.janssen@uwv.nl" },
14
+ ]
15
+ description = "A Robotframework library for IBM MQ"
16
+ keywords = ["robotframework", "ibm", "mqlibrary"]
17
+ readme = "README.md"
18
+ license = "EUPL-1.2"
19
+ requires-python = ">=3.9.0"
20
+ classifiers = [
21
+ "Development Status :: 3 - Alpha",
22
+ "Intended Audience :: Developers",
23
+ "Topic :: Software Development :: Testing",
24
+ "Framework :: Robot Framework",
25
+ "Framework :: Robot Framework :: Library",
26
+ "Programming Language :: Python :: 3",
27
+ "Operating System :: OS Independent",
28
+ ]
29
+ dependencies = [
30
+ "robotframework (>=7.3.0,<8.3.0)",
31
+ "ibmmq (>=2.0.0,<3.0.0)"
32
+ ]
33
+
34
+ [dependency-groups]
35
+ dev = [
36
+ "pyyaml>=6.0.3",
37
+ ]
38
+
39
+
40
+ [project.optional-dependencies]
41
+ deploy = ["twine", "build", "wheel"]
42
+
43
+ [project.urls]
44
+ Homepage = "https://github.com/nluwv/robotframework-ibmmq"
45
+ Documentation = "https://robotframework-ibmmq.netlify.app/IBMMQLibrary.html"
46
+ Repository = "https://github.com/nluwv/robotframework-ibmmq.git"
47
+ Issues = "https://github.com/nluwv/robotframework-ibmmq/issues"
48
+
49
+ [tool.uv.build-backend]
50
+ module-name = "IBMMQLibrary"
@@ -0,0 +1,320 @@
1
+ import os
2
+ import subprocess
3
+
4
+ import ibmmq
5
+ from robot.api import logger
6
+ from robot.api.deco import keyword, library
7
+ from robot.utils import timestr_to_secs
8
+
9
+ from .exceptions import MQMIError_handling
10
+
11
+
12
+ def _new_md() -> ibmmq.MD:
13
+ """Return a fresh MQ Message Descriptor (MD)."""
14
+ md = ibmmq.MD()
15
+ md.Version = ibmmq.CMQC.MQMD_VERSION_2
16
+ return md
17
+
18
+
19
+ @library
20
+ class IBMMQLibrary:
21
+ """
22
+ IBMMQLibrary - A Robot Framework Library for IBM MQ Integration with multi-alias connection support.
23
+
24
+ This library enables easy interaction with IBM MQ message queues from Robot Framework.
25
+
26
+ It supports multiple simultaneous connections to different queue managers through aliases.
27
+ If only one connection is used, the alias parameter can be omitted (defaults to "default").
28
+
29
+ MQ server and MQ client must use compatible code pages.
30
+ If code pages are not compatible error `2539: MQRC_CHANNEL_CONFIG_ERROR` will occur.
31
+ If the client uses codepage 65001 (the windows equivalent of UTF-8) and the server uses codepage 850
32
+ the channel name will not be found and the connection will fail.
33
+ Forcing the client code page can be done with the `chcp` command.
34
+ For example `chcp 437` to use default ascii code page.
35
+
36
+ === Examples ===
37
+ | `Connect MQ` queue_manager=QM1
38
+ | ... hostname=localhost
39
+ | ... port=1414
40
+ | ... channel=DEV.APP.SVRCONN
41
+ | ... username=%{USERNAME}
42
+ | ... password=%{PASSWORD}
43
+ | `Put MQ Message` queue=QUEUE.TEST message=Hello
44
+ | ${messages} `Get MQ Message` queue=QUEUE.TEST max_messages=1
45
+ | `Clear MQ Queue` queue=QUEUE.TEST
46
+ | `Disconnect MQ`
47
+ """
48
+ ROBOT_LIBRARY_SCOPE = 'GLOBAL'
49
+
50
+ def __init__(self):
51
+ self.connections = {} # Holds aliases mapped to queue manager connections
52
+
53
+ # Check for unsupported code page 65001 (Windows utf-8)
54
+ if os.name == 'nt':
55
+ codepage = int(subprocess.getoutput("chcp").split()[-1])
56
+ if codepage == 65001:
57
+ logger.warn("This shell uses codepage 65001, which is not supported by MQ, you will likely encounter error: 2539: MQRC_CHANNEL_CONFIG_ERROR.\n Use `chcp 437` in your shell to switch to a compatible codepage.")
58
+
59
+ @keyword(name="Connect MQ", tags=["Connection"])
60
+ def connect_mq(self, queue_manager: str, hostname: str, port: int, channel: str, username: str | None = None, password: str | None = None, alias: str = "default"):
61
+ """
62
+ Connects to the remote queue manager and stores it under an alias.
63
+
64
+ | =Argument= | =Description= |
65
+ | ``queue_manager`` | Name of the queue manager |
66
+ | ``hostname`` | Hostname of the MQ server |
67
+ | ``port`` | Port used to connect |
68
+ | ``channel`` | Channel name used for communication |
69
+ | ``username`` | Username for authentication (optional) |
70
+ | ``password`` | Password for authentication (optional) |
71
+ | ``alias`` | Connection alias (default = "default") |
72
+
73
+ === Example ===
74
+ | `Connect MQ` queue_manager=QM1
75
+ | ... hostname=localhost
76
+ | ... port=1414
77
+ | ... channel=DEV.APP.SVRCONN
78
+ | ... username=&{USERNAME}
79
+ | ... password=&{PASSWORD}
80
+ """
81
+ if alias in self.connections:
82
+ raise ValueError(f"Alias '{alias}' is already connected.")
83
+
84
+ try:
85
+ conn_info = f"{hostname}({port})"
86
+ cd = ibmmq.CD()
87
+ cd.ChannelName = channel
88
+ cd.ConnectionName = conn_info
89
+ cd.ChannelType = ibmmq.CMQXC.MQCHT_CLNTCONN
90
+ cd.TransportType = ibmmq.CMQXC.MQXPT_TCP
91
+
92
+ qmgr = ibmmq.QueueManager(None)
93
+ qmgr.connect_tcp_client(
94
+ name=queue_manager,
95
+ cd=cd,
96
+ channel=channel,
97
+ conn_name=conn_info,
98
+ user=username,
99
+ password=password
100
+ )
101
+ self.connections[alias] = qmgr
102
+ logger.info(f"Connected to MQ with alias '{alias}'.")
103
+
104
+ except ibmmq.MQMIError as e:
105
+ MQMIError_handling(e, mqmanager=queue_manager, mqhost=hostname, mqport=port, mqchannel=channel)
106
+ except Exception as e:
107
+ logger.error(f"Failed to connect to MQ: {e}")
108
+ raise
109
+
110
+
111
+ def _get_qmgr(self, alias: str):
112
+ if alias not in self.connections:
113
+ raise ValueError("No valid MQ alias provided or no default connection available.")
114
+ return self.connections[alias]
115
+
116
+
117
+ @keyword(name="Put MQ Message", tags=["Put"])
118
+ def put_message(self, queue: str, message: str, ccsid: int = 1208, alias: str = "default"):
119
+ """
120
+ Puts a message onto the target queue.
121
+
122
+ | =Argument= | =Description= |
123
+ | ``queue`` | Name of the target queue |
124
+ | ``message`` | Message content to put on the queue |
125
+ | ``ccsid`` | Character encoding set (default 1208) |
126
+ | ``alias`` | Alias of the MQ connection |
127
+
128
+ === Example ===
129
+ | `Put MQ Message` queue=QUEUE.TEST message=Hello World
130
+ """
131
+ qmgr = self._get_qmgr(alias)
132
+ queue_obj = None
133
+ try:
134
+ queue_obj = ibmmq.Queue(qmgr, queue)
135
+ md = _new_md()
136
+ md.CodedCharSetId = ccsid
137
+ message_bytes = message.encode('utf-8')
138
+ queue_obj.put(message_bytes, md)
139
+ logger.info(f"Message put on queue '{queue}' via alias '{alias}'.")
140
+ finally:
141
+ if queue_obj:
142
+ queue_obj.close()
143
+
144
+
145
+ @keyword(name="Get MQ Messages", tags=["Retrieve"])
146
+ def get_messages(self, queue: str, message_amount: int = 1, convert: bool = True, timeout: str = 0, alias: str = "default") -> list:
147
+ """
148
+ Retrieves messages from a queue and returns it as a list.
149
+ Removes the messages from the queue on retrieval.
150
+
151
+ | =Argument= | =Description= |
152
+ | ``queue`` | Queue to read messages from |
153
+ | ``message_amount`` | Number of messages to retrieve, fails if it doesn't |
154
+ | ``convert`` | Convert message (MQGMO_CONVERT) if True |
155
+ | ``timeout`` | Timeout per message in seconds (default = 0) |
156
+ | ``alias`` | Alias of the MQ connection (default = "default") |
157
+
158
+ === Example ===
159
+ | ${msgs} `Get MQ Messages` queue=QUEUE.TEST message_amount=5 timeout=2
160
+ """
161
+ qmgr = self._get_qmgr(alias)
162
+ queue_obj = None
163
+ messages = []
164
+ try:
165
+ gmo = ibmmq.GMO()
166
+ gmo.Options = ibmmq.CMQC.MQGMO_WAIT | (ibmmq.CMQC.MQGMO_CONVERT if convert else 0)
167
+
168
+ timeout_ms = int(timestr_to_secs(timeout) * 1000)
169
+ gmo.WaitInterval = timeout_ms
170
+
171
+ queue_obj = ibmmq.Queue(qmgr, queue)
172
+ for _ in range(message_amount):
173
+ md = _new_md()
174
+ try:
175
+ message = queue_obj.get(None, md, gmo)
176
+ try:
177
+ decoded = message.decode("utf-8")
178
+ except UnicodeDecodeError:
179
+ logger.warn("UTF-8 decoding failed, falling back to ISO-8859-1.")
180
+ decoded = message.decode("iso-8859-1")
181
+ messages.append(decoded)
182
+ logger.info(f"Received message from queue '{queue}': {decoded}")
183
+ except ibmmq.MQMIError as e:
184
+ if e.reason == ibmmq.CMQC.MQRC_NO_MSG_AVAILABLE:
185
+ logger.info(f"No more messages available on queue '{queue}'.")
186
+ break
187
+ logger.error(f"Failed to get message from queue '{queue}': {e}")
188
+ raise
189
+ if len(messages) == message_amount:
190
+ return messages
191
+ message = f"Expected {message_amount} message(s), but received {len(messages)}."
192
+ logger.error(message)
193
+ raise AssertionError(message)
194
+ finally:
195
+ if queue_obj:
196
+ queue_obj.close()
197
+
198
+
199
+ @keyword(name="Browse MQ Messages", tags=["Retrieve"])
200
+ def browse_messages(self, queue: str, max_messages: int = 1, timeout: str = '5s', convert: bool = True, alias: str = "default") -> list:
201
+ """
202
+ Browses for messages on ``queue`` and returns them in a list.
203
+ Doesn't delete a message after being browsed.
204
+
205
+ | =Argument= | =Description= |
206
+ | ``queue`` | Queue to listen on |
207
+ | ``max_messages`` | Maximum number of messages it tries to retrieve |
208
+ | ``timeout`` | Timeout per message in milliseconds (default 5000) |
209
+ | ``convert`` | Convert message encoding if True |
210
+ | ``alias`` | MQ connection alias (default = "default") |
211
+
212
+ === Example ===
213
+ | ${msgs} `Browse MQ Messages` queue=QUEUE.TEST max_messages=3
214
+ """
215
+ qmgr = self._get_qmgr(alias)
216
+ messages = []
217
+ queue_obj = None
218
+ try:
219
+ timeout_ms = int(timestr_to_secs(timeout) * 1000)
220
+ queue_obj = ibmmq.Queue(qmgr, queue, ibmmq.CMQC.MQOO_BROWSE)
221
+ logger.info(f"Browsing messages on '{queue}' via alias '{alias}'...")
222
+
223
+ for i in range(max_messages):
224
+ gmo = ibmmq.GMO()
225
+ gmo.Options = ibmmq.CMQC.MQGMO_WAIT | (ibmmq.CMQC.MQGMO_CONVERT if convert else 0)
226
+ gmo.WaitInterval = timeout_ms
227
+ gmo.Options |= ibmmq.CMQC.MQGMO_BROWSE_FIRST if i == 0 else ibmmq.CMQC.MQGMO_BROWSE_NEXT
228
+
229
+ md = _new_md()
230
+ try:
231
+ message = queue_obj.get(None, md, gmo)
232
+ try:
233
+ decoded = message.decode("utf-8")
234
+ except UnicodeDecodeError:
235
+ logger.warn("UTF-8 decoding failed, falling back to ISO-8859-1.")
236
+ decoded = message.decode("iso-8859-1")
237
+ messages.append(decoded)
238
+ logger.info(f"Browsed message {i + 1}: {decoded}")
239
+ except ibmmq.MQMIError as e:
240
+ if e.reason == ibmmq.CMQC.MQRC_NO_MSG_AVAILABLE:
241
+ logger.info(f"No more messages available to browse on queue '{queue}'.")
242
+ break
243
+ logger.error(f"Error while browsing message: {e}")
244
+ raise
245
+ return messages
246
+ finally:
247
+ if queue_obj:
248
+ queue_obj.close()
249
+
250
+
251
+ @keyword(name="Clear MQ Queue", tags=["Cleanup"])
252
+ def clear_queue(self, queue: str, alias: str = "default"):
253
+ """
254
+ Removes all messages from a queue immediately without waiting.
255
+
256
+ | =Argument= | =Description= |
257
+ | ``queue`` | The queue to clear |
258
+ | ``alias`` | MQ connection alias (default = "default") |
259
+
260
+ === Example ===
261
+ | `Clear MQ Queue` queue=QUEUE.TEST
262
+ """
263
+ qmgr = self._get_qmgr(alias)
264
+ queue_obj = None
265
+ try:
266
+ gmo = ibmmq.GMO()
267
+ gmo.Options = ibmmq.CMQC.MQGMO_NO_WAIT
268
+ gmo.WaitInterval = 0
269
+ queue_obj = ibmmq.Queue(qmgr, queue, ibmmq.CMQC.MQOO_INPUT_AS_Q_DEF)
270
+
271
+ logger.info(f"Clearing all messages from queue '{queue}' via alias '{alias}'...")
272
+
273
+ cleared_count = 0
274
+ while True:
275
+ md = _new_md()
276
+ try:
277
+ _ = queue_obj.get(None, md, gmo)
278
+ cleared_count += 1
279
+ except ibmmq.MQMIError as e:
280
+ if e.reason == ibmmq.CMQC.MQRC_NO_MSG_AVAILABLE:
281
+ break
282
+ logger.error(f"Error while clearing queue: {e}")
283
+ raise
284
+
285
+ logger.info(f"Cleared {cleared_count} message(s) from queue '{queue}' via alias '{alias}'.")
286
+
287
+ # Final verification that queue is empty
288
+ md = _new_md()
289
+ try:
290
+ queue_obj.get(None, md, gmo)
291
+ raise AssertionError(f"Queue '{queue}' still contains messages after clearing.")
292
+ except ibmmq.MQMIError as e:
293
+ if e.reason == ibmmq.CMQC.MQRC_NO_MSG_AVAILABLE:
294
+ logger.info(f"Verified queue '{queue}' is empty.")
295
+ else:
296
+ logger.error(f"Unexpected error while verifying queue: {e}")
297
+ raise
298
+ finally:
299
+ if queue_obj:
300
+ queue_obj.close()
301
+
302
+
303
+ @keyword(name="Disconnect MQ", tags=["Connection"])
304
+ def disconnect_mq(self, alias: str = "default"):
305
+ """Disconnects a specific MQ connection using alias."""
306
+ if alias in self.connections:
307
+ try:
308
+ self.connections[alias].disconnect()
309
+ logger.info(f"Disconnected from MQ alias '{alias}'.")
310
+ except Exception as e:
311
+ logger.warn(f"Error while disconnecting alias '{alias}': {e}")
312
+ finally:
313
+ del self.connections[alias]
314
+
315
+
316
+ @keyword(name="Disconnect All MQ Connections", tags=["Connection"])
317
+ def disconnect_all(self):
318
+ """Disconnects all active MQ connections."""
319
+ for alias in list(self.connections.keys()):
320
+ self.disconnect_mq(alias)
@@ -0,0 +1,3 @@
1
+ from .IBMMQLibrary import IBMMQLibrary
2
+
3
+ # Allow Robot Framework to use the class as IBMMQLibrary
@@ -0,0 +1,24 @@
1
+ import ibmmq
2
+ from robot.api import logger
3
+
4
+ def MQMIError_handling(mqerror, **manager_settings):
5
+ match mqerror.reason:
6
+ case ibmmq.CMQC.MQRC_Q_MGR_NAME_ERROR: # 2058
7
+ message = f"Queue Manager {manager_settings['mqmanager']} does not exist or is unavailable."
8
+ logger.error(message)
9
+ raise ValueError(mqerror)
10
+ case ibmmq.CMQC.MQRC_HOST_NOT_AVAILABLE: # 2538
11
+ message = f"Cannot connect to MQ host {manager_settings['mqhost']}:{manager_settings['mqport']}. Host not available or refusing connection."
12
+ logger.error(message)
13
+ raise ValueError(mqerror)
14
+ case ibmmq.CMQC.MQRC_UNKNOWN_CHANNEL_NAME: # 2540
15
+ message = f"Channel {manager_settings['mqchannel']} is unknown or not configured correctly on the MQ server."
16
+ logger.error(message)
17
+ raise ValueError(mqerror)
18
+ case ibmmq.CMQC.MQRC_SECURITY_ERROR: # 2063
19
+ message = f"Authentication failed. Check username and password for queue manager {manager_settings['mqmanager']}."
20
+ logger.error(message)
21
+ raise ValueError(mqerror)
22
+ case _:
23
+ logger.error(f"MQ connection failed with reason code {mqerror.reason}: {mqerror}") # Generiek maken
24
+ raise