rubywmq 2.0.2 → 2.1.0

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.
Files changed (48) hide show
  1. checksums.yaml +4 -4
  2. data/Gemfile +10 -0
  3. data/Gemfile.lock +37 -0
  4. data/LICENSE.txt +1 -1
  5. data/README.md +29 -47
  6. data/Rakefile +12 -76
  7. data/examples/each_a.rb +2 -3
  8. data/examples/each_b.rb +4 -5
  9. data/examples/each_header.rb +5 -6
  10. data/examples/files_to_q.rb +7 -8
  11. data/examples/get_a.rb +3 -5
  12. data/examples/get_client.rb +9 -10
  13. data/examples/put1_a.rb +2 -3
  14. data/examples/put1_b.rb +4 -7
  15. data/examples/put1_c.rb +6 -6
  16. data/examples/put_a.rb +0 -2
  17. data/examples/put_b.rb +5 -7
  18. data/examples/put_dlh.rb +11 -12
  19. data/examples/put_dynamic_q.rb +7 -7
  20. data/examples/put_group_a.rb +3 -4
  21. data/examples/put_group_b.rb +7 -7
  22. data/examples/put_rfh.rb +13 -11
  23. data/examples/put_rfh2_a.rb +9 -10
  24. data/examples/put_rfh2_b.rb +9 -9
  25. data/examples/put_xmit_q.rb +63 -8
  26. data/examples/q_to_files.rb +6 -7
  27. data/examples/request.rb +20 -18
  28. data/examples/server.rb +19 -16
  29. data/ext/extconf.rb +2 -1
  30. data/ext/extconf_client.rb +3 -3
  31. data/ext/generate/generate_const.rb +30 -23
  32. data/ext/generate/generate_reason.rb +70 -72
  33. data/ext/generate/generate_structs.rb +20 -19
  34. data/ext/generate/wmq_structs.erb +67 -67
  35. data/ext/wmq.c +0 -16
  36. data/ext/wmq.h +0 -16
  37. data/ext/wmq_message.c +8 -24
  38. data/ext/wmq_mq_load.c +5 -17
  39. data/ext/wmq_queue.c +73 -90
  40. data/ext/wmq_queue_manager.c +115 -108
  41. data/lib/wmq/message.rb +36 -34
  42. data/lib/wmq/queue_manager.rb +22 -19
  43. data/lib/wmq/version.rb +1 -1
  44. data/rubywmq.gemspec +38 -0
  45. data/test/queue_manager_test.rb +334 -0
  46. data/test/test_helper.rb +14 -0
  47. metadata +16 -26
  48. data/tests/test.rb +0 -318
@@ -6,11 +6,11 @@ module WMQ
6
6
  # Example
7
7
  # require 'wmq/wmq'
8
8
  # require 'wmq/wmq_const_admin'
9
- # WMQ::QueueManager.connect(:q_mgr_name=>'REID', :connection_name=>'localhost(1414)') do |qmgr|
9
+ # WMQ::QueueManager.connect(q_mgr_name: 'REID', connection_name: 'localhost(1414)') do |qmgr|
10
10
  # qmgr.mqsc('dis ql(*)').each {|item| p item }
11
11
  # end
12
12
  def mqsc(mqsc_text)
13
- self.execute(:command=>:escape, :escape_type=>WMQ::MQET_MQSC, :escape_text=>mqsc_text).collect {|item| item[:escape_text] }
13
+ execute(command: :escape, escape_type: WMQ::MQET_MQSC, escape_text: mqsc_text).collect { |item| item[:escape_text] }
14
14
  end
15
15
 
16
16
  # Put a reply message back to the sender
@@ -44,19 +44,20 @@ module WMQ
44
44
  if parms[:request_message].descriptor[:msg_type] == WMQ::MQMT_REQUEST
45
45
  request = parms.delete(:request_message)
46
46
 
47
- reply = parms[:message] ||= Message.new(:data=>parms[:data])
47
+ reply = parms[:message] ||= Message.new(data: parms[:data])
48
48
  reply.descriptor[:msg_type] = WMQ::MQMT_REPLY
49
49
  reply.descriptor[:expiry] = request.descriptor[:expiry]
50
50
  reply.descriptor[:priority] = request.descriptor[:priority]
51
51
  reply.descriptor[:persistence]= request.descriptor[:persistence]
52
- reply.descriptor[:format] = request.descriptor[:format]
52
+ reply.descriptor[:format] = request.descriptor[:format]
53
53
 
54
54
  # Set Correlation Id based on report options supplied
55
- if request.descriptor[:report] & WMQ::MQRO_PASS_CORREL_ID != 0
56
- reply.descriptor[:correl_id] = request.descriptor[:correl_id]
57
- else
58
- reply.descriptor[:correl_id] = request.descriptor[:msg_id]
59
- end
55
+ reply.descriptor[:correl_id] =
56
+ if request.descriptor[:report] & WMQ::MQRO_PASS_CORREL_ID != 0
57
+ request.descriptor[:correl_id]
58
+ else
59
+ request.descriptor[:msg_id]
60
+ end
60
61
 
61
62
  # Set Message Id based on report options supplied
62
63
  if request.descriptor[:report] & WMQ::MQRO_PASS_MSG_ID != 0
@@ -83,24 +84,26 @@ module WMQ
83
84
  # are retained.
84
85
  #
85
86
  def put_to_dead_letter_q(parms)
86
- message = parms[:message] ||= Message.new(:data=>parms[:data])
87
- dlh = {
88
- :header_type =>:dead_letter_header,
89
- :reason =>parms.delete(:reason),
90
- :dest_q_name =>parms.delete(:q_name),
91
- :dest_q_mgr_name =>self.name}
87
+ message = parms[:message] ||= Message.new(data: parms[:data])
88
+ dlh = {
89
+ header_type: :dead_letter_header,
90
+ reason: parms.delete(:reason),
91
+ dest_q_name: parms.delete(:q_name),
92
+ dest_q_mgr_name: name
93
+ }
92
94
 
93
95
  message.headers.unshift(dlh)
94
- parms[:q_name]='SYSTEM.DEAD.LETTER.QUEUE' #TODO Should be obtained from QMGR config
95
- return self.put(parms)
96
+ parms[:q_name] = 'SYSTEM.DEAD.LETTER.QUEUE' #TODO Should be obtained from QMGR config
97
+
98
+ put(parms)
96
99
  end
97
100
 
98
101
  # Expose Commands directly as Queue Manager methods
99
102
  def method_missing(name, *args)
100
103
  if args.size == 1
101
- self.execute({:command=>name}.merge(args[0]))
104
+ execute({ command: name }.merge(args[0]))
102
105
  elsif args.size == 0
103
- self.execute({:command=>name})
106
+ execute(command: name)
104
107
  else
105
108
  raise("Invalid arguments supplied to QueueManager#:#{name}, args:#{args}")
106
109
  end
data/lib/wmq/version.rb CHANGED
@@ -1,3 +1,3 @@
1
1
  module WMQ #:nodoc
2
- VERSION = "2.0.2"
2
+ VERSION = '2.1.0'
3
3
  end
data/rubywmq.gemspec ADDED
@@ -0,0 +1,38 @@
1
+ $:.push File.expand_path('../lib', __FILE__)
2
+
3
+ # Maintain your gem's version:
4
+ require 'wmq/version'
5
+ require 'rake/file_list'
6
+
7
+ # Describe your gem and declare its dependencies:
8
+ Gem::Specification.new do |s|
9
+ # Exclude locally compiled files since they are platform specific
10
+ excludes = [
11
+ /lib.wmq.constants\.rb/,
12
+ /lib.wmq.constants_admin\.rb/,
13
+ /ext.wmq_structs\.c/,
14
+ /ext.wmq_reason\.c/,
15
+ /ext.Makefile/,
16
+ /ext.*\.o/,
17
+ /ext.wmq\.so/,
18
+ /\.gem$/,
19
+ /\.log$/,
20
+ /nbproject/
21
+ ]
22
+ s.name = 'rubywmq'
23
+ s.version = WMQ::VERSION
24
+ s.platform = Gem::Platform::RUBY
25
+ s.authors = ['Reid Morrison']
26
+ s.email = ['reidmo@gmail.com']
27
+ s.homepage = 'https://github.com/reidmorrison/rubywmq'
28
+ s.summary = 'Native Ruby interface into WebSphere MQ'
29
+ s.description = 'RubyWMQ is a high performance native Ruby interface into WebSphere MQ.'
30
+ s.files = Rake::FileList['./**/*'].exclude(*excludes).map { |f| f.sub(/^\.\//, '') } + ['.document']
31
+ s.test_files = Dir['test/**/*']
32
+ s.license = 'Apache License V2.0'
33
+ s.has_rdoc = true
34
+ s.extensions << 'ext/extconf.rb'
35
+ s.requirements << 'WebSphere MQ v5.3, v6 or v7 Client or Server with Development Kit'
36
+ s.required_ruby_version = '>= 1.9'
37
+ end
38
+
@@ -0,0 +1,334 @@
1
+ require_relative 'test_helper'
2
+
3
+ # Unit Test for RocketJob::Job
4
+ class WMQTest < Minitest::Test
5
+ context WMQ do
6
+ setup do
7
+ @queue_manager = WMQ::QueueManager.new(q_mgr_name: 'TEST') #, connection_name: 'localhost(1414)')
8
+ @queue_manager.connect
9
+
10
+ # Create Queue and clear any messages from the queue
11
+ @in_queue = WMQ::Queue.new(
12
+ queue_manager: @queue_manager,
13
+ mode: :input,
14
+ dynamic_q_name: 'UNIT.TEST.*',
15
+ q_name: 'SYSTEM.DEFAULT.MODEL.QUEUE',
16
+ fail_if_exists: false
17
+ )
18
+ @in_queue.open
19
+ @in_queue.each { |message|}
20
+
21
+ # Open same queue for Output. Queue should be created by now
22
+ @out_queue = WMQ::Queue.new(
23
+ queue_manager: @queue_manager,
24
+ mode: :output,
25
+ q_name: @in_queue.name
26
+ )
27
+ @out_queue.open
28
+ end
29
+
30
+ teardown do
31
+ @out_queue.close if @out_queue
32
+ @in_queue.close if @in_queue
33
+ @queue_manager.disconnect if @queue_manager
34
+ end
35
+
36
+ context 'exceptions' do
37
+ should 'raise exceptions' do
38
+ assert_raises(TypeError) do
39
+ WMQ::QueueManager.new(1)
40
+ end
41
+ WMQ::QueueManager.new(exception_on_error: nil)
42
+ assert_raises(TypeError) do
43
+ WMQ::QueueManager.new(exception_on_error: 1)
44
+ end
45
+ assert_raises(TypeError) do
46
+ WMQ::QueueManager.new(q_mgr_name: 2).connect
47
+ end
48
+ assert_raises(WMQ::WMQException) do
49
+ WMQ::QueueManager.new(q_mgr_name: 'bad').connect
50
+ end
51
+ end
52
+ end
53
+
54
+ context 'queue manager' do
55
+ should 'exist' do
56
+ assert_equal Object, WMQ::QueueManager.superclass
57
+ assert_equal WMQ::QueueManager, @queue_manager.class
58
+ end
59
+
60
+ should 'open_queue' do
61
+ @queue_manager.open_queue(
62
+ mode: :output,
63
+ q_name: {
64
+ q_name: @in_queue.name,
65
+ q_mgr_name: @queue_manager.name
66
+ }
67
+ ) do |test_queue|
68
+ assert_equal(true, test_queue.put(data: 'Hello World'))
69
+ message = WMQ::Message.new
70
+ assert_equal(true, @in_queue.get(message: message))
71
+ assert_equal('Hello World', message.data)
72
+ end
73
+ end
74
+
75
+ should 'execute' do
76
+ array = @queue_manager.inquire_q(
77
+ q_name: @in_queue.name,
78
+ q_type: WMQ::MQQT_LOCAL,
79
+ current_q_depth: nil
80
+ )
81
+ assert_equal 1, array.size
82
+ assert_equal @in_queue.name, array[0][:q_name]
83
+
84
+ assert_equal true, @queue_manager.inquire_process(process_name: '*').size > 0
85
+ assert_raises WMQ::WMQException do
86
+ @queue_manager.inquire_q(q_name: 'BADQUEUENAME*')
87
+ end
88
+ assert_equal 1, @queue_manager.ping_q_mgr.size
89
+ end
90
+
91
+ should 'mqsc' do
92
+ array = @queue_manager.mqsc("dis ql(#{@in_queue.name})")
93
+ assert_equal 1, array.size
94
+ assert_equal true, array[0].include?("QUEUE(#{@in_queue.name})")
95
+ end
96
+
97
+ should 'put1' do
98
+ data = 'Some Test Data'
99
+ assert_equal true, @queue_manager.put(q_name: @in_queue.name, data: data)
100
+
101
+ message = WMQ::Message.new
102
+ assert_equal true, @in_queue.get(message: message)
103
+ assert_equal data, message.data
104
+ end
105
+
106
+ end
107
+
108
+ context 'Queue' do
109
+ should 'send and receive message' do
110
+ assert_equal @out_queue.put(data: 'Hello World'), true
111
+ message = WMQ::Message.new
112
+ assert_equal @in_queue.get(message: message), true
113
+ assert_equal message.data, 'Hello World'
114
+ end
115
+
116
+ should 'group messages' do
117
+ # Clear out queue of any messages
118
+ @in_queue.each { |message|}
119
+
120
+ msg = WMQ::Message.new
121
+ msg.data = 'First'
122
+ msg.descriptor[:msg_flags] = WMQ::MQMF_MSG_IN_GROUP
123
+ assert_equal(@out_queue.put(message: msg, options: WMQ::MQPMO_LOGICAL_ORDER), true)
124
+
125
+ msg.data = 'Second'
126
+ assert_equal(@out_queue.put(message: msg, options: WMQ::MQPMO_LOGICAL_ORDER), true)
127
+
128
+ msg.data = 'Last'
129
+ msg.descriptor[:msg_flags] = WMQ::MQMF_LAST_MSG_IN_GROUP
130
+ assert_equal(@out_queue.put(message: msg, options: WMQ::MQPMO_LOGICAL_ORDER), true)
131
+ end
132
+ end
133
+
134
+ context 'Message' do
135
+ should 'dynamic_buffer' do
136
+ test_sizes = [0, 1, 100, 101, 102, 500, 65534, 65535, 65536, 65537, 1*1024*1024, 4*1024*1024]
137
+ test_sizes.each do |size|
138
+ str = '0123456789ABCDEF' * (size/16) + '0123456789ABCDEF'[0, size%16]
139
+ assert_equal str.length, size
140
+ assert_equal @out_queue.put(data: str), true
141
+ end
142
+
143
+ # First test the browse mechanism
144
+ counter = 0
145
+ @queue_manager.open_queue(mode: :browse, q_name: @in_queue.name) do |browse_queue|
146
+ browse_queue.each do |message|
147
+ size = test_sizes[counter]
148
+ assert_equal(size, message.data.length)
149
+ str = '0123456789ABCDEF' * (size/16) + '0123456789ABCDEF'[0, size%16]
150
+ assert_equal(str, message.data)
151
+ counter = counter + 1
152
+ end
153
+ end
154
+ assert_equal(test_sizes.size, counter)
155
+
156
+ # Now retrieve the messages destructively
157
+ message = WMQ::Message.new
158
+ test_sizes.each do |size|
159
+ assert_equal(true, @in_queue.get(message: message, match: WMQ::MQMO_NONE))
160
+ assert_equal(size, message.data.length)
161
+ str = '0123456789ABCDEF' * (size/16) + '0123456789ABCDEF'[0, size%16]
162
+ assert_equal(str, message.data)
163
+ end
164
+ end
165
+
166
+ should 'dead letter header' do
167
+ # TODO: Something has changed with DLH since MQ V6
168
+ skip
169
+ dlh = {
170
+ header_type: :dead_letter_header,
171
+ reason: WMQ::MQRC_UNKNOWN_REMOTE_Q_MGR,
172
+ dest_q_name: 'ORIGINAL_QUEUE_NAME',
173
+ dest_q_mgr_name: 'BAD_Q_MGR',
174
+ put_appl_name: 'TestApp.exe',
175
+ }
176
+
177
+ verify_header(dlh, WMQ::MQFMT_DEAD_LETTER_HEADER)
178
+ end
179
+
180
+ should 'cics' do
181
+ cics = {
182
+ header_type: :cics,
183
+ reason: WMQ::MQRC_UNKNOWN_REMOTE_Q_MGR,
184
+ facility: 'TOKEN123',
185
+ reply_to_format: WMQ::MQFMT_STRING
186
+ }
187
+ verify_header(cics, WMQ::MQFMT_NONE)
188
+ end
189
+
190
+ should 'ims' do
191
+ ims = {
192
+ header_type: :ims,
193
+ l_term_override: 'LTERM',
194
+ reply_to_format: WMQ::MQFMT_STRING
195
+ }
196
+ verify_header(ims, WMQ::MQFMT_STRING)
197
+ end
198
+
199
+ should 'transmission_header' do
200
+ xqh = {
201
+ header_type: :xmit_q_header,
202
+ remote_q_name: 'SOME_REMOTE_QUEUE',
203
+ remote_q_mgr_name: 'SOME_REMOTE_Q_MGR',
204
+ msg_type: WMQ::MQMT_REQUEST,
205
+ msg_id: 'my message Id'
206
+ }
207
+ verify_header(xqh, WMQ::MQFMT_STRING)
208
+ end
209
+
210
+ should 'rf_header' do
211
+ rfh = {
212
+ header_type: :rf_header,
213
+ name_value: {
214
+ ' name s' => ' v a "l" u e 1 ',
215
+ 'n a m e 2 ' => 'v a l u e 2',
216
+ '' => ['"', '""', '"""', '""""', ''],
217
+ 'name3' => ['"value3"', '', '"', ' value 43"']
218
+ }
219
+ }
220
+ verify_header(rfh, WMQ::MQFMT_STRING)
221
+ end
222
+
223
+ should 'rf_header_2' do
224
+ rfh2 = {
225
+ header_type: :rf_header_2,
226
+ xml: [
227
+ '<hello>to the world</hello>',
228
+ '<another>xml like string</another>'
229
+ ],
230
+ }
231
+ verify_header(rfh2, WMQ::MQFMT_STRING)
232
+ end
233
+
234
+ should 'multiple_headers' do
235
+ headers = [
236
+ {header_type: :rf_header_2,
237
+ xml: [
238
+ '<hello>to the world</hello>',
239
+ '<another>xml like string</another>'],
240
+ },
241
+
242
+ {
243
+ header_type: :rf_header,
244
+ name_value: {
245
+ ' name s' => ' v a l u e 1 ',
246
+ 'n a m e 2 ' => 'v a l u e 2',
247
+ 'name3' => ['value3', '', 'value 43']
248
+ }
249
+ },
250
+
251
+ {
252
+ header_type: :ims,
253
+ l_term_override: 'LTERM',
254
+ reply_to_format: WMQ::MQFMT_STRING
255
+ },
256
+
257
+ {
258
+ header_type: :rf_header,
259
+ name_value: {
260
+ ' name s' => ' v a l u e 1 ',
261
+ 'n a m e 2 ' => 'v a l u e 2',
262
+ 'name3' => ['value3', '', 'value 43']
263
+ }
264
+ },
265
+
266
+ {
267
+ header_type: :cics,
268
+ reason: WMQ::MQRC_UNKNOWN_REMOTE_Q_MGR,
269
+ facility: 'TOKEN123',
270
+ reply_to_format: WMQ::MQFMT_STRING
271
+ },
272
+
273
+ {
274
+ header_type: :rf_header_2,
275
+ xml: ['<hello>to the world</hello>', '<another>xml like string</another>'],
276
+ },
277
+
278
+ {
279
+ header_type: :xmit_q_header,
280
+ remote_q_name: 'SOME_REMOTE_QUEUE',
281
+ remote_q_mgr_name: 'SOME_REMOTE_Q_MGR',
282
+ msg_type: WMQ::MQMT_REQUEST,
283
+ msg_id: 'my message Id'
284
+ },
285
+ ]
286
+ verify_multiple_headers(headers, WMQ::MQFMT_STRING)
287
+ end
288
+
289
+ should 'xmit_q_header' do
290
+ headers = [
291
+ {
292
+ header_type: :xmit_q_header,
293
+ remote_q_name: 'SOME_REMOTE_QUEUE',
294
+ remote_q_mgr_name: 'SOME_REMOTE_Q_MGR',
295
+ msg_type: WMQ::MQMT_REQUEST,
296
+ msg_id: 'my message Id'},
297
+
298
+ {
299
+ header_type: :ims,
300
+ l_term_override: 'LTERM',
301
+ reply_to_format: WMQ::MQFMT_STRING
302
+ },
303
+ ]
304
+ verify_multiple_headers(headers, WMQ::MQFMT_STRING)
305
+ end
306
+ end
307
+ end
308
+
309
+ def verify_header(header, format)
310
+ verify_multiple_headers([header], format)
311
+ end
312
+
313
+ def verify_multiple_headers(headers, format)
314
+ data = 'Some Test Data'
315
+ message = WMQ::Message.new
316
+ message.data = data
317
+ message.descriptor[:format] = format
318
+ message.headers = headers
319
+ #assert_equal(true,@queue_manager.put(q_name: @in_queue.name, message: message))
320
+ assert_equal(true, @out_queue.put(message: message))
321
+
322
+ message = WMQ::Message.new
323
+ assert_equal true, @in_queue.get(message: message)
324
+ assert_equal data, message.data
325
+ assert_equal headers.size, message.headers.size
326
+ count = 0
327
+ headers.each do |header|
328
+ reply_header = message.headers[count]
329
+ header.each_pair { |key, value| assert_equal(value, reply_header[key]) }
330
+ count = count + 1
331
+ end
332
+ end
333
+
334
+ end