da_funk 3.33.1 → 3.34.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 8eeac1f3c7449183cfd65b190bd2ca9515f586eb55af7e70fa6ac38762a8ae80
4
- data.tar.gz: be5906723b2ef951f592bf8434626f7cac9b20a01f699432132692e0a2df8428
3
+ metadata.gz: b3a687d541cc683675f05e5ebcf8d28504a929c97a57606e9af3d5f238f04def
4
+ data.tar.gz: f3a1c52920ca5d00f3b43a3d9e513dad9ae883b7167c4b8c37509089bc489af6
5
5
  SHA512:
6
- metadata.gz: 9667b789d09b2d1ccc41734b1112a243eec58e91504c85618f9177c4e007ab9ec59e857c99f867295794b5bba3d2c33c25e66e2061fa09b47ee2c3c7b2f929b5
7
- data.tar.gz: 693e92596f8be1c74e338e2d3b6bebe20d9b4c9f190f4bee820e76046350039cd8317379a3e9b59101183a9525881110a6e8a94c4527d5601de36bb7c00fde77
6
+ metadata.gz: 7c7d8b462ac97d930628a593a27bc5a7388d3543683f9950db9449d34d22159c68250dc6a8cd2aa24abbed62c5b0ddd09711d0ca0b040924e9337d4f85e1b1e0
7
+ data.tar.gz: 40d72d5925bfaf49d65bc54ccbfb2c231d8d2f548fd13f784a8bc1bf1b4c863418251e4a1b773ef44836a01dc3fe53321f5f736e33ae9666fd7783546676eac2
data/Gemfile CHANGED
@@ -4,4 +4,13 @@ gem 'cloudwalk'
4
4
  gem 'rubocop', require: false
5
5
  gem 'funky-mock'
6
6
 
7
- gemspec
7
+ group :test do
8
+ gem 'minitest', group: :test
9
+ gem 'simplecov', group: :test
10
+ end
11
+
12
+ group :development, :test do
13
+ gem 'byebug'
14
+ end
15
+
16
+ gemspec
data/Gemfile.lock CHANGED
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- da_funk (3.33.1)
4
+ da_funk (3.34.0)
5
5
  archive-zip (~> 0.5)
6
6
  bundler
7
7
  cloudwalk_handshake
@@ -15,17 +15,20 @@ GEM
15
15
  archive-zip (0.12.0)
16
16
  io-like (~> 0.3.0)
17
17
  ast (2.4.1)
18
+ byebug (11.1.3)
18
19
  cloudwalk (1.15.0)
19
20
  bundler
20
21
  rake
21
22
  cloudwalk_handshake (1.21.3)
22
23
  funky-simplehttp (~> 0.6)
24
+ docile (1.3.5)
23
25
  funky-emv (1.4.1)
24
26
  funky-tlv (~> 0.2)
25
27
  funky-mock (0.1.0)
26
28
  funky-simplehttp (0.6.0)
27
29
  funky-tlv (0.2.3)
28
30
  io-like (0.3.1)
31
+ minitest (5.14.4)
29
32
  parallel (1.19.2)
30
33
  parser (2.7.2.0)
31
34
  ast (~> 2.4.1)
@@ -47,6 +50,10 @@ GEM
47
50
  rubocop-ast (1.1.0)
48
51
  parser (>= 2.7.1.5)
49
52
  ruby-progressbar (1.10.1)
53
+ simplecov (0.18.5)
54
+ docile (~> 1.1)
55
+ simplecov-html (~> 0.11)
56
+ simplecov-html (0.12.3)
50
57
  unicode-display_width (1.7.0)
51
58
  yard (0.9.25)
52
59
 
@@ -56,12 +63,15 @@ PLATFORMS
56
63
  x86-mingw32
57
64
 
58
65
  DEPENDENCIES
66
+ byebug
59
67
  cloudwalk
60
68
  da_funk!
61
69
  funky-mock
62
70
  funky-simplehttp
71
+ minitest
63
72
  rubocop
73
+ simplecov
64
74
  yard
65
75
 
66
76
  BUNDLED WITH
67
- 2.1.4
77
+ 2.2.7
data/README.md CHANGED
File without changes
data/README_GUIDE.md CHANGED
File without changes
data/Rakefile CHANGED
@@ -90,3 +90,17 @@ end
90
90
  task "test:all" => :build
91
91
  task "test:unit" => :build
92
92
  task "test:integration" => :build
93
+
94
+ Rake::TestTask.new('test:iso8583') do |t|
95
+ Bundler.require(:default, :test)
96
+ t.libs << File.join("lib", "da_funk", "helper")
97
+ t.libs << File.join("lib","iso8583")
98
+ t.libs << File.join("test", "iso8583")
99
+ t.test_files = FileList['test/iso8583/**/*_test.rb']
100
+ end
101
+
102
+ task "test:iso8583:cov" do
103
+ ENV.store('COV', '1')
104
+ Bundler.require(:default, :test)
105
+ Rake::Task["test:iso8583"].execute
106
+ end
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
@@ -1,4 +1,4 @@
1
1
  module DaFunk
2
- VERSION="3.33.1"
2
+ VERSION="3.34.0"
3
3
  end
4
4
 
data/lib/device.rb CHANGED
File without changes
data/lib/device/crypto.rb CHANGED
File without changes
File without changes
data/lib/device/io.rb CHANGED
File without changes
File without changes
File without changes
File without changes
File without changes
data/lib/file_db.rb CHANGED
File without changes
@@ -14,16 +14,51 @@ module ISO8583
14
14
  # transparently by the Message class.
15
15
  class Bitmap
16
16
  include DaFunk::Helper
17
+
18
+ class << self
19
+ # Parse the bytes in string and return the Bitmap and bytes remaining in `str`
20
+ # after the bitmap is taken away.
21
+ def parse(str, hex_bitmap = false, bitmap_size = 64)
22
+ bmp = Bitmap.new(str, hex_bitmap, bitmap_size)
23
+
24
+ rest = if bmp.hex_bitmap?
25
+ str[bmp.size_in_bytes_hex, str.length]
26
+ else
27
+ str[bmp.size_in_bytes, str.length]
28
+ end
29
+
30
+ [ bmp, rest ]
31
+ end
32
+ end
33
+
34
+ # bitmap_size defines the size in bits of bitmap. It has to be multiple of 8 (a byte of 8 bits)
35
+ attr_reader :bitmap_size
36
+
37
+ # additional_bitmap defines if the bit 1 (left to right) indicates the presence of another
38
+ # bitmap just after the current one
39
+ attr_reader :additional_bitmap
40
+
41
+ attr_reader :bitmaps
42
+
17
43
  # create a new Bitmap object. In case an iso message
18
44
  # is passed in, that messages bitmap will be parsed. If
19
45
  # not, this initializes and empty bitmap.
20
- def initialize(message = nil, hex_bitmap=false)
21
- @bmp = Array.new(128, false)
22
- @hex_bitmap = hex_bitmap
46
+ def initialize(message = nil, hex_bitmap=false, bitmap_size = 64, additional_bitmap = true)
47
+ raise ISO8583Exception.new "wrong bitmap_size: #{bitmap_size}" if bitmap_size % 8 != 0
48
+
49
+ @bitmap_size = bitmap_size
50
+ @bmp = Array.new(bitmap_size, false)
51
+ @hex_bitmap = hex_bitmap
52
+ @additional_bitmap = additional_bitmap
53
+ @bitmaps = 1
23
54
 
24
55
  message ? initialize_from_message(message) : nil
25
56
  end
26
57
 
58
+ def additional_bitmap?
59
+ !!@additional_bitmap
60
+ end
61
+
27
62
  def hex_bitmap?
28
63
  !!@hex_bitmap
29
64
  end
@@ -38,22 +73,40 @@ module ISO8583
38
73
  @bmp[i-1]
39
74
  end
40
75
 
41
- # Set the bit to the indicated value. Only `true` sets the
42
- # bit, any other value unsets it.
43
- def []=(i, value)
44
- if i > 128
45
- raise ISO8583Exception.new("Bits > 128 are not permitted.")
46
- elsif i < 2
47
- raise ISO8583Exception.new("Bits < 2 are not permitted (continutation bit is set automatically)")
48
- end
49
- @bmp[i-1] = (value == true)
50
- end
51
-
52
76
  # Sets bit #i
53
77
  def set(i)
78
+ if additional_bitmap?
79
+ raise ISO8583Exception, "field #{i} shouldn't be set (continuation bit is set automatically)" if i % bitmap_size == 1
80
+ end
81
+
82
+ if i > bitmap_size
83
+ raise ISO8583Exception, "can't set field #{i}, bitmap_size == #{bitmap_size}" unless additional_bitmap?
84
+
85
+ quo = i / bitmap_size
86
+ rem = i % bitmap_size
87
+ @bitmaps = rem > 0 ? quo + 1 : quo
88
+ new_bmp = Array.new(@bitmaps * bitmap_size, false)
89
+ @bmp.each_with_index { |v, idx| new_bmp[idx] = v }
90
+ 0.upto(@bitmaps - 2) do |pos|
91
+ new_bmp[pos * bitmap_size] = true
92
+ end
93
+ @bmp = new_bmp
94
+ end
54
95
  self[i] = true
55
96
  end
56
97
 
98
+ def size_in_bits
99
+ bitmaps * bitmap_size
100
+ end
101
+
102
+ def size_in_bytes
103
+ size_in_bits / 8
104
+ end
105
+
106
+ def size_in_bytes_hex
107
+ size_in_bytes * 2
108
+ end
109
+
57
110
  # Unsets bit #i
58
111
  def unset(i)
59
112
  self[i] = false
@@ -64,13 +117,13 @@ module ISO8583
64
117
  if RUBY_ENGINE == 'mruby'
65
118
  # Convert binary to hex, by slicing the binary in 4 bytes chuncks
66
119
  bitmap_hex = ""
67
- str = ""
120
+ str = String.new("", encoding: 'ASCII-8BIT')
68
121
  self.to_s.chars.reverse.each_with_index do |ch, i|
69
122
  str << ch
70
123
  next if i == 0
71
124
  if (i+1) % 4 == 0
72
125
  bitmap_hex << str.reverse.to_i(2).to_s(16)
73
- str = ""
126
+ str = String.new("", encoding: 'ASCII-8BIT')
74
127
  end
75
128
  end
76
129
  unless str.empty?
@@ -78,29 +131,20 @@ module ISO8583
78
131
  end
79
132
  bitmap_hex.reverse.upcase
80
133
  else
81
- [to_s].pack("B*").force_encoding('UTF-8')
134
+ [to_s].pack("B*")
82
135
  end
83
136
  end
84
137
  alias_method :to_b, :to_bytes
85
138
 
86
139
  def to_hex
87
- value = self.to_s.to_i(2).to_s(16).upcase
88
- if value.respond_to? :force_encoding
89
- value.force_encoding('UTF-8')
90
- else
91
- value
92
- end
140
+ self.to_s.to_i(2).to_s(16).upcase.ljust(size_in_bytes_hex, '0')
93
141
  end
94
142
 
95
143
  # Generate a String representation of this bitmap in the form:
96
144
  # 01001100110000011010110110010100100110011000001101011011001010
97
145
  def to_s
98
- #check whether any `high` bits are set
99
- ret = (65..128).find {|bit| !!self[bit]}
100
- high, @bmp[0] = ret ? [128, true] : [64, false]
101
-
102
- str = ""
103
- 1.upto(high) do|i|
146
+ str = String.new("", encoding: "ASCII-8BIT")
147
+ 1.upto(size_in_bits) do |i|
104
148
  str << (self[i] ? '1' : '0')
105
149
  end
106
150
 
@@ -110,6 +154,12 @@ module ISO8583
110
154
 
111
155
  private
112
156
 
157
+ # Set the bit to the indicated value. Only `true` sets the
158
+ # bit, any other value unsets it.
159
+ def []=(i, value)
160
+ @bmp[i-1] = (value == true)
161
+ end
162
+
113
163
  def convert_hex_to_binary(str)
114
164
  str.chars.reverse.inject("") do |string, ch|
115
165
  string + ch.to_i(16).to_s(2).rjust(4, "0").reverse
@@ -118,40 +168,30 @@ module ISO8583
118
168
 
119
169
  def initialize_from_message(message)
120
170
  bmp = if hex_bitmap?
121
- rjust(convert_hex_to_binary(message[0..15]), 64, '0')
171
+ slice_range = (bitmap_size * 2) / 8 - 1
172
+ rjust(convert_hex_to_binary(message[0..slice_range]), bitmap_size, '0')
122
173
  else
123
- message.unpack("B64")[0]
174
+ message.unpack("B#{bitmap_size}")[0]
124
175
  end
125
176
 
126
- if bmp[0,1] == "1"
127
- bmp = if hex_bitmap?
128
- rjust(convert_hex_to_binary(message[0..31]), 128, '0')
129
- else
130
- message.unpack("B128")[0]
131
- end
177
+ if additional_bitmap?
178
+ has_next_bitmap = bmp[0] == "1"
179
+ while has_next_bitmap
180
+ @bitmaps += 1
181
+ bmp = if hex_bitmap?
182
+ slice_range = (bitmap_size * bitmaps * 2) / 8 - 1
183
+ rjust(convert_hex_to_binary(message[0..slice_range]), bitmap_size * bitmaps, '0')
184
+ else
185
+ message.unpack("B#{bitmap_size * bitmaps}")[0]
186
+ end
187
+ has_next_bitmap = bmp[bitmap_size * (bitmaps - 1)] == "1"
188
+ end
132
189
  end
133
190
 
134
191
  0.upto(bmp.length-1) do |i|
135
192
  @bmp[i] = (bmp[i,1] == "1")
136
193
  end
137
194
  end
138
-
139
- class << self
140
- # Parse the bytes in string and return the Bitmap and bytes remaining in `str`
141
- # after the bitmap is taken away.
142
- def parse(str, hex_bitmap = false)
143
- bmp = Bitmap.new(str, hex_bitmap)
144
-
145
- rest = if bmp.hex_bitmap?
146
- bmp[1] ? str[32, str.length] : str[16, str.length]
147
- else
148
- bmp[1] ? str[16, str.length] : str[8, str.length]
149
- end
150
-
151
- [ bmp, rest ]
152
- end
153
- end
154
-
155
195
  end
156
196
  end
157
197
 
data/lib/iso8583/codec.rb CHANGED
@@ -106,11 +106,11 @@ module ISO8583
106
106
  Packed_Number.encoder = lambda { |val|
107
107
  val = val.to_s
108
108
  val = val.length % 2 == 0 ? val : "0"+val
109
- raise ISO8583Exception.new("Invalid value: #{val} must be numeric!") unless val =~ /^[0-9]*$/
110
- [val].pack("H*")
109
+ raise ISO8583Exception.new("Invalid value: #{val} must be numeric!") unless val =~ /^[0-9A-Fa-f]*$/
110
+ String.new([val].pack("H*"), encoding: "ASCII-8BIT")
111
111
  }
112
112
  Packed_Number.decoder = lambda{|encoded|
113
- d = encoded.unpack("H*")[0].to_i
113
+ encoded.unpack("H*")[0].to_i
114
114
  }
115
115
 
116
116
  A_Codec = Codec.new
data/lib/iso8583/field.rb CHANGED
@@ -72,7 +72,7 @@ module ISO8583
72
72
  when Integer
73
73
  raise ISO8583Exception.new("Too long: #{value} (#{name})! length=#{length}") if encoded_value.length > length
74
74
  raise ISO8583Exception.new("Too short: #{value} (#{name})! length=#{length}") if encoded_value.length < length
75
- ""
75
+ String.new("", encoding: 'ASCII-8BIT')
76
76
  when Field
77
77
  raise ISO8583Exception.new("Max lenth exceeded: #{value}, max: #{max}") if max && encoded_value.length > max
78
78
  length.encode(encoded_value.length)
@@ -85,11 +85,46 @@ module ISO8583
85
85
  end
86
86
 
87
87
  class BCDField < Field
88
+ attr_accessor :data_length
89
+ attr_accessor :byte_length
88
90
  # This corrects the length for BCD fields, as their encoded length is half (+ parity) of the
89
91
  # content length. E.g. 123 (length = 3) encodes to "\x01\x23" (length 2)
90
92
  def length
91
- _length = super
92
- (_length % 2) != 0 ? (_length / 2) + 1 : _length / 2
93
+ @byte_length
94
+ end
95
+
96
+ def encode(value)
97
+ begin
98
+ encoded_value = codec.encode(value)
99
+ @data_length = value.size
100
+ @byte_length = encoded_value.bytes.size
101
+ rescue ISO8583Exception => e
102
+ ContextLog.exception(e, e.backtrace, "#{e.message} (#{name})") if Object.const_defined?(:ContextLog)
103
+ raise ISO8583Exception.new(e.message+" (#{name})")
104
+ end
105
+
106
+ if padding
107
+ if padding.arity == 1
108
+ encoded_value = padding.call(encoded_value)
109
+ elsif padding.arity == 2
110
+ encoded_value = padding.call(encoded_value, length)
111
+ end
112
+ end
113
+
114
+ len_str = case length
115
+ when Integer
116
+ raise ISO8583Exception.new("Too long: #{value} (#{name})! length=#{length}") if encoded_value.length > length
117
+ raise ISO8583Exception.new("Too short: #{value} (#{name})! length=#{length}") if encoded_value.length < length
118
+ String.new("", encoding: 'ASCII-8BIT')
119
+ when Field
120
+ raise ISO8583Exception.new("Max length exceeded: #{value}, max: #{max}") if max && @byte_length > max
121
+ length.encode(@data_length)
122
+ else
123
+ raise ISO8583Exception.new("Invalid length (#{length}) for '#{name}' field")
124
+ end
125
+
126
+ len_str + encoded_value
127
+
93
128
  end
94
129
  end
95
130
 
@@ -4,6 +4,8 @@
4
4
  # this distribution
5
5
  #++
6
6
 
7
+ require_relative '../da_funk/helper'
8
+
7
9
  module ISO8583
8
10
  include DaFunk::Helper
9
11
 
@@ -16,7 +18,7 @@ module ISO8583
16
18
  # The following fields are available:
17
19
  #
18
20
  # [+LL+] special form to de/encode variable length indicators, two bytes ASCII numerals
19
- # [+LLL+] special form to de/encode variable length indicators, two bytes ASCII numerals
21
+ # [+LLL+] special form to de/encode variable length indicators, three bytes ASCII numerals
20
22
  # [+LL_BCD+] special form to de/encode variable length indicators, two BCD digits
21
23
  # [+LLVAR_N+] two byte variable length ASCII numeral, payload ASCII numerals
22
24
  # [+LLLVAR_N+] three byte variable length ASCII numeral, payload ASCII numerals
@@ -117,9 +117,16 @@ module ISO8583
117
117
  # ISO8583 allows hex or binary bitmap, so it should be configurable
118
118
  attr_reader :use_hex_bitmap
119
119
 
120
+ # ignore_mti allow use of Message without mti. Useful for fields with variable subfields
121
+ attr_reader :ignore_mti
122
+
123
+ # bitmap_size define the size of bitmap to be used, in number of bits.
124
+ # It should be a multiple of 8 (a byte of 8 bits)
125
+ attr_reader :bitmap_size
126
+
120
127
  # Instantiate a new instance of this type of Message
121
128
  # optionally specifying an mti.
122
- def initialize(mti = nil, use_hex_bitmap = false)
129
+ def initialize(mti = nil, use_hex_bitmap = false, ignore_mti = false, bitmap_size = 64)
123
130
  # values is an internal field used to collect all the
124
131
  # bmp number | bmp name | field en/decoders | values
125
132
  # which are set in this message.
@@ -127,7 +134,8 @@ module ISO8583
127
134
 
128
135
  self.mti = mti if mti
129
136
  @use_hex_bitmap = use_hex_bitmap
130
-
137
+ @ignore_mti = ignore_mti
138
+ @bitmap_size = bitmap_size
131
139
  end
132
140
 
133
141
  # Set the mti of the Message using either the actual value
@@ -143,7 +151,9 @@ module ISO8583
143
151
  # mes = MyMessage.new
144
152
  # mes.mti = 1100 # or mes.mti = "Authorization Request Acquirer Gateway"
145
153
  def mti=(value)
146
- num, name = _get_mti_definition(value)
154
+ raise ISO8583Exception.new "can't set MTI when `ignore_mti` is set" if ignore_mti
155
+
156
+ num, _ = _get_mti_definition(value)
147
157
  @mti = num
148
158
  end
149
159
 
@@ -180,9 +190,12 @@ module ISO8583
180
190
 
181
191
  # Retrieve the byte representation of the bitmap.
182
192
  def to_b
183
- raise ISO8583Exception.new "no MTI set!" unless mti
184
- mti_enc = self.class._mti_format.encode(mti).force_encoding('UTF-8')
185
- mti_enc << _body.join.force_encoding('UTF-8')
193
+ raise ISO8583Exception.new "no MTI set!" if !(ignore_mti || mti)
194
+
195
+ return _body.join if ignore_mti
196
+
197
+ mti_enc = self.class._mti_format.encode(mti)
198
+ mti_enc << _body.join
186
199
  end
187
200
 
188
201
  # Returns a nicely formatted representation of this
@@ -209,12 +222,12 @@ module ISO8583
209
222
  # Returns an array of two byte arrays:
210
223
  # [bitmap_bytes, message_bytes]
211
224
  def _body
212
- bitmap = Bitmap.new
213
- message = ""
225
+ bitmap = Bitmap.new(nil, use_hex_bitmap, bitmap_size)
226
+ message = String.new("", encoding: 'ASCII-8BIT')
214
227
  @values.keys.sort.each do |bmp_num|
215
228
  bitmap.set(bmp_num)
216
229
  enc_value = @values[bmp_num].encode
217
- message << enc_value.force_encoding('UTF-8')
230
+ message << enc_value
218
231
  end
219
232
 
220
233
  if use_hex_bitmap
@@ -356,12 +369,12 @@ module ISO8583
356
369
  end
357
370
 
358
371
  # Parse the bytes `str` returning a message of the defined type.
359
- def parse(str, use_hex_bitmap = false)
360
- message = self.new(nil, use_hex_bitmap)
372
+ def parse(str, use_hex_bitmap = false, bitmap_size = 64)
373
+ message = self.new(nil, use_hex_bitmap, false, bitmap_size)
361
374
 
362
375
  message.mti, rest = _mti_format.parse(str)
363
376
 
364
- bmp, rest = Bitmap.parse(rest, use_hex_bitmap)
377
+ bmp, rest = Bitmap.parse(rest, use_hex_bitmap, bitmap_size)
365
378
 
366
379
  bmp.each {|bit|
367
380
  bmp_def = _definitions[bit]
data/lib/iso8583/util.rb CHANGED
@@ -30,7 +30,7 @@ module ISO8583
30
30
  end
31
31
 
32
32
  def _conv(str, mapping)
33
- _str = ""
33
+ _str = String.new("", encoding: "ASCII-8BIT")
34
34
  str.each_byte{|byte|
35
35
  _str << mapping[byte]
36
36
  }
@@ -0,0 +1,277 @@
1
+ require_relative 'minitest_helper'
2
+
3
+ module ISO8583
4
+ class TestBitmap < Minitest::Test
5
+ def test_parse_with_hex_bitmap_without_additional_bitmap
6
+ message = "7020000000008000165432123456789876000000000000001500986"
7
+ hex_bitmap = true
8
+ bitmap_size = 64
9
+
10
+ bitmap, _ = Bitmap.parse(message, hex_bitmap, bitmap_size)
11
+
12
+ expect = "7020000000008000"
13
+ assert_equal(expect, bitmap.to_hex)
14
+ end
15
+
16
+ def test_parse_with_bin_bitmap_without_additional_bitmap
17
+ message = String.new("\x70\x20\x00\x00\x00\x00\x80\x00165432123456789876000000000000001500986", encoding: "ASCII-8BIT")
18
+ hex_bitmap = false
19
+ bitmap_size = 64
20
+
21
+ bitmap, _ = Bitmap.parse(message, hex_bitmap, bitmap_size)
22
+
23
+ expect = String.new("\x70\x20\x00\x00\x00\x00\x80\x00", encoding: "ASCII-8BIT")
24
+ assert_equal(expect, bitmap.to_bytes)
25
+ end
26
+
27
+ def test_parse_with_hex_bitmap_having_one_additional_bitmap
28
+ message = "F02000000000800000000000000000021654321234567898760000000000000015009860a53ec23-8f0b-4328-a51f-b9202dad7b8b"
29
+ hex_bitmap = true
30
+ bitmap_size = 64
31
+
32
+ bitmap, _ = Bitmap.parse(message, hex_bitmap, bitmap_size)
33
+
34
+ expect = "F0200000000080000000000000000002"
35
+ assert_equal(expect, bitmap.to_hex)
36
+ end
37
+
38
+ def test_parse_with_bin_bitmap_having_one_additional_bitmap
39
+ message = String.new("\xF0\x20\x00\x00\x00\x00\x80\x00\x00\x00\x00\x00\x00\x00\x00\x021654321234567898760000000000000015009860a53ec23-8f0b-4328-a51f-b9202dad7b8b", encoding: 'ASCII-8BIT')
40
+ hex_bitmap = false
41
+ bitmap_size = 64
42
+
43
+ bitmap, _ = Bitmap.parse(message, hex_bitmap, bitmap_size)
44
+
45
+ expect = String.new("\xF0\x20\x00\x00\x00\x00\x80\x00\x00\x00\x00\x00\x00\x00\x00\x02", encoding: "ASCII-8BIT")
46
+ assert_equal(expect, bitmap.to_bytes)
47
+ end
48
+
49
+ def test_parse_with_hex_bitmap_having_more_additionals_bitmap
50
+ message = "808002blablabla"
51
+ hex_bitmap = true
52
+ bitmap_size = 8
53
+
54
+ bitmap, _ = Bitmap.parse(message, hex_bitmap, bitmap_size)
55
+
56
+ expect = "808002"
57
+ assert_equal(expect, bitmap.to_hex)
58
+ assert_equal(true, bitmap[23])
59
+ end
60
+
61
+ def test_parse_returning_remainder_of_message_small_bitmap_size
62
+ message = "40blablabla"
63
+ hex_bitmap = true
64
+ bitmap_size = 8
65
+
66
+ _, rest = Bitmap.parse(message, hex_bitmap, bitmap_size)
67
+
68
+ expect = "blablabla"
69
+ assert_equal(expect, rest)
70
+ end
71
+
72
+ def test_parse_returning_remainder_of_message_usual_bitmap_size
73
+ message = "4000000000000000foobarbaz"
74
+ hex_bitmap = true
75
+ bitmap_size = 64
76
+
77
+ _, rest = Bitmap.parse(message, hex_bitmap, bitmap_size)
78
+
79
+ expect = "foobarbaz"
80
+ assert_equal(expect, rest)
81
+ end
82
+
83
+ def test_parse_returning_remainder_of_message_big_bitmap_size
84
+ message = "40000000000000000000000000000000bazbarfoo"
85
+ hex_bitmap = true
86
+ bitmap_size = 128
87
+
88
+ _, rest = Bitmap.parse(message, hex_bitmap, bitmap_size)
89
+
90
+ expect = "bazbarfoo"
91
+ assert_equal(expect, rest)
92
+ end
93
+
94
+ def test_raises_on_wrong_bitmap_size
95
+ e = assert_raises { Bitmap.new(nil, false, 1) }
96
+ assert_equal(ISO8583Exception, e.class)
97
+ assert_equal('wrong bitmap_size: 1', e.message)
98
+ end
99
+
100
+ def test_set_and_get_value
101
+ bitmap = Bitmap.new(nil, false, 8)
102
+ bitmap.set(2)
103
+ assert_equal(true, bitmap[2])
104
+ assert_equal(false, bitmap[1])
105
+ end
106
+
107
+ def test_avoid_set_bit_greater_than_size
108
+ bitmap = Bitmap.new(nil, false, 8, false)
109
+ e = assert_raises { bitmap.set(9) }
110
+ assert_equal(ISO8583Exception, e.class)
111
+ assert_equal("can't set field 9, bitmap_size == 8", e.message)
112
+ end
113
+
114
+ def test_allow_set_bit_1_when_no_has_additional_bitmap
115
+ bitmap = Bitmap.new(nil, false, 8, false)
116
+ bitmap.set(1)
117
+ assert_equal(true, bitmap[1])
118
+ end
119
+
120
+ def test_avoid_set_bit_1_when_has_additional_bitmap
121
+ bitmap = Bitmap.new(nil, false, 8, true)
122
+ e = assert_raises { bitmap.set(1) }
123
+ assert_equal(ISO8583Exception, e.class)
124
+ assert_equal("field 1 shouldn't be set (continuation bit is set automatically)", e.message)
125
+ end
126
+
127
+ def test_set_continuation_bit
128
+ bitmap = Bitmap.new(nil, false, 8, true)
129
+ bitmap.set(20)
130
+ assert_equal(true, bitmap[1])
131
+ assert_equal(true, bitmap[9])
132
+ assert_equal(false, bitmap[17])
133
+ assert_equal(true, bitmap[20])
134
+ end
135
+
136
+ def test_set_continuation_bit_with_bitmap_size_of_64
137
+ bitmap = Bitmap.new(nil, false, 64, true)
138
+ bitmap.set(180)
139
+ assert_equal(true, bitmap[1])
140
+ assert_equal(true, bitmap[65])
141
+ assert_equal(false, bitmap[129])
142
+ assert_equal(true, bitmap[180])
143
+ end
144
+
145
+ def test_unset_field
146
+ bitmap = Bitmap.new(nil, false, 8, false)
147
+ assert_equal(false, bitmap[1])
148
+ bitmap.set(1)
149
+ assert_equal(true, bitmap[1])
150
+ bitmap.unset(1)
151
+ assert_equal(false, bitmap[1])
152
+ end
153
+
154
+ def test_to_s_bitmap_size_8_bits
155
+ bitmap = Bitmap.new(nil, false, 8, false)
156
+ bitmap.set(2)
157
+ bitmap.set(7)
158
+
159
+ assert_equal('01000010', bitmap.to_s)
160
+ end
161
+
162
+ def test_to_s_bitmap_size_8_bits_having_additional_bitmap
163
+ bitmap = Bitmap.new(nil, false, 8, true)
164
+ bitmap.set(2)
165
+ bitmap.set(10)
166
+
167
+ assert_equal('1100000001000000', bitmap.to_s)
168
+ end
169
+
170
+ def test_to_s_bitmap_size_64_bits
171
+ bitmap = Bitmap.new(nil, false, 64, true)
172
+ bitmap.set(2)
173
+ bitmap.set(3)
174
+ bitmap.set(7)
175
+ bitmap.set(11)
176
+ bitmap.set(39)
177
+
178
+ assert_equal('0110001000100000000000000000000000000010000000000000000000000000', bitmap.to_s)
179
+ end
180
+
181
+ def test_to_s_bitmap_size_64_bits_having_additional_bitmap
182
+ bitmap = Bitmap.new(nil, false, 64, true)
183
+ bitmap.set(2)
184
+ bitmap.set(3)
185
+ bitmap.set(7)
186
+ bitmap.set(11)
187
+ bitmap.set(39)
188
+ bitmap.set(127)
189
+
190
+ assert_equal('11100010001000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000010', bitmap.to_s)
191
+ end
192
+
193
+ def test_to_hex_without_fields
194
+ bitmap = Bitmap.new(nil, true, 8, true)
195
+
196
+ expected = "00"
197
+ assert_equal(expected, bitmap.to_hex)
198
+ end
199
+
200
+ def test_to_hex_with_many_fields
201
+ bitmap = Bitmap.new(nil, true, 64, true)
202
+ bitmap.set(2)
203
+ bitmap.set(3)
204
+ bitmap.set(4)
205
+ bitmap.set(5)
206
+ bitmap.set(6)
207
+ bitmap.set(7)
208
+ bitmap.set(8)
209
+ bitmap.set(66)
210
+
211
+ expected = "FF000000000000004000000000000000"
212
+
213
+ assert_equal(expected, bitmap.to_hex)
214
+ end
215
+
216
+ def test_to_b_bitmap_size_8
217
+ bitmap = Bitmap.new(nil, false, 8, false)
218
+ bitmap.set(2)
219
+ bitmap.set(3)
220
+ bitmap.set(4)
221
+ bitmap.set(5)
222
+ bitmap.set(6)
223
+ bitmap.set(7)
224
+
225
+ expected = String.new("\x7E", encoding: 'ASCII-8BIT')
226
+
227
+ assert_equal(expected, bitmap.to_b)
228
+ end
229
+
230
+ def test_to_b_bitmap_size_8_having_additional_bitmap
231
+ bitmap = Bitmap.new(nil, false, 8, true)
232
+ bitmap.set(2)
233
+ bitmap.set(3)
234
+ bitmap.set(4)
235
+ bitmap.set(5)
236
+ bitmap.set(6)
237
+ bitmap.set(7)
238
+ bitmap.set(11)
239
+
240
+ expected = String.new("\xFE\x20", encoding: 'ASCII-8BIT')
241
+
242
+ assert_equal(expected, bitmap.to_b)
243
+ end
244
+
245
+ def test_to_b_bitmap_size_64
246
+ bitmap = Bitmap.new(nil, false, 64, false)
247
+ bitmap.set(2)
248
+ bitmap.set(3)
249
+ bitmap.set(4)
250
+ bitmap.set(5)
251
+ bitmap.set(6)
252
+ bitmap.set(7)
253
+ bitmap.set(8)
254
+ bitmap.set(64)
255
+
256
+ expected = String.new("\x7F\x00\x00\x00\x00\x00\x00\x01", encoding: 'ASCII-8BIT')
257
+
258
+ assert_equal(expected, bitmap.to_b)
259
+ end
260
+
261
+ def test_to_b_bitmap_size_64_having_additional_bitmap
262
+ bitmap = Bitmap.new(nil, false, 64, true)
263
+ bitmap.set(2)
264
+ bitmap.set(3)
265
+ bitmap.set(4)
266
+ bitmap.set(5)
267
+ bitmap.set(6)
268
+ bitmap.set(7)
269
+ bitmap.set(8)
270
+ bitmap.set(66)
271
+
272
+ expected = String.new("\xFF\x00\x00\x00\x00\x00\x00\x00\x40\x00\x00\x00\x00\x00\x00\x00", encoding: 'ASCII-8BIT')
273
+
274
+ assert_equal(expected, bitmap.to_b)
275
+ end
276
+ end
277
+ end
@@ -0,0 +1,111 @@
1
+ require_relative 'minitest_helper'
2
+
3
+ module ISO8583
4
+ class TestMTIMessage < Message
5
+ mti_format N, length: 4
6
+ mti 100, "Test Authorization"
7
+
8
+ bmp 2, "foo", ANS, length: 3
9
+ end
10
+
11
+ class TestMTIMessageBCDPacked < Message
12
+ mti_format N_BCD, length: 4
13
+ mti 100, "Test Authorization"
14
+
15
+ bmp 2, "foo", ANS, length: 3
16
+ end
17
+
18
+ class TestNoMTIMessage < Message
19
+ bmp 2, "foo", ANS, length: 3
20
+ end
21
+
22
+ class TestMessageInitialization < Minitest::Test
23
+ def test_ignore_mti_field_set
24
+ msg = TestNoMTIMessage.new(nil, true, true)
25
+ assert_equal true, msg.ignore_mti
26
+ end
27
+
28
+ def test_cant_set_mit_if_ignore_mti
29
+ msg = TestNoMTIMessage.new(nil, true, true)
30
+ assert_raises { msg.mti = 100 }
31
+ end
32
+
33
+ def test_can_set_mti_unless_ignore_mti
34
+ msg = TestMTIMessage.new(100, true)
35
+
36
+ assert_equal 100, msg.mti
37
+ end
38
+
39
+ def test_set_mti_bcd_packed_bin_bitmap
40
+ msg = TestMTIMessageBCDPacked.new(100, false)
41
+
42
+ expected = String.new("\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00", encoding: 'ASCII-8BIT')
43
+ assert_equal expected, msg.to_b
44
+ end
45
+ end
46
+
47
+ class Test_to_b_Method < Minitest::Test
48
+ def test_raises_when_no_mti_and_no_ignore_mti
49
+ msg = TestMTIMessage.new(nil, true)
50
+ assert_raises {msg.to_b}
51
+ end
52
+
53
+ def test_return_bitmap_without_mti_set_and_hex_bitmap
54
+ msg = TestNoMTIMessage.new(nil, true, true, 24)
55
+ msg[2] = "bar"
56
+ assert_equal("400000bar", msg.to_b)
57
+ end
58
+
59
+ def test_return_bitmap_without_mti_set_and_bin_bitmap
60
+ msg = TestNoMTIMessage.new(nil, false, true, 24)
61
+ msg[2] = "bar"
62
+
63
+ expected = String.new("\x40\x00\x00bar", encoding: 'ASCII-8BIT')
64
+ assert_equal(expected, msg.to_b)
65
+ end
66
+ end
67
+
68
+ class Test_parse_Method < Minitest::Test
69
+
70
+ def test_parse_with_hex_bitmap
71
+ msg = "010040bar"
72
+
73
+ isomsg = TestMTIMessage.parse(msg, true, 8)
74
+
75
+ expected = 100
76
+ assert_equal(expected, isomsg.mti)
77
+ expected = "bar"
78
+ assert_equal(expected, isomsg[2])
79
+ end
80
+
81
+ def test_parse_with_bin_bitmap
82
+ msg = "0100\x40bar"
83
+
84
+ isomsg = TestMTIMessage.parse(msg, false, 8)
85
+
86
+ expected = 100
87
+ assert_equal(expected, isomsg.mti)
88
+ expected = "bar"
89
+ assert_equal(expected, isomsg[2])
90
+ end
91
+
92
+ def test_parse_raises_when_undefined_field
93
+ msg = "0100\x20bar"
94
+
95
+ e = assert_raises { TestMTIMessage.parse(msg, false, 8) }
96
+ assert_equal(ISO8583ParseException, e.class)
97
+ assert_equal("The message contains fields not defined", e.message)
98
+ end
99
+
100
+ def test_parse_raises_when_undefined_field
101
+ msg = "0100\x40\x00\x00\x00\x00\x00\x00\x00bar"
102
+
103
+ isomsg = TestMTIMessage.parse(msg, false)
104
+
105
+ expected = 100
106
+ assert_equal(expected, isomsg.mti)
107
+ expected = "bar"
108
+ assert_equal(expected, isomsg[2])
109
+ end
110
+ end
111
+ end
@@ -0,0 +1,11 @@
1
+ if ENV['COV']
2
+ require 'simplecov'
3
+ SimpleCov.start
4
+ end
5
+
6
+ require 'byebug'
7
+ require 'minitest/autorun'
8
+ PROJECT_ROOT = File.join(File.dirname(File.expand_path(__FILE__)), '..', '..')
9
+ Dir.glob(File.join(PROJECT_ROOT, 'lib', 'iso8583', '**', '*.rb')).each do |file|
10
+ require file
11
+ end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: da_funk
3
3
  version: !ruby/object:Gem::Version
4
- version: 3.33.1
4
+ version: 3.34.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Thiago Scalone
8
- autorequire:
8
+ autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2021-02-19 00:00:00.000000000 Z
11
+ date: 2021-05-28 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rake
@@ -218,6 +218,9 @@ files:
218
218
  - test/integration/mrb_eval_test.rb
219
219
  - test/integration/notification_test.rb
220
220
  - test/integration/params_dat_test.rb
221
+ - test/iso8583/bitmap_test.rb
222
+ - test/iso8583/message_test.rb
223
+ - test/iso8583/minitest_helper.rb
221
224
  - test/resources/shared/bitmap.dat
222
225
  - test/resources/shared/bitmap_gp.dat
223
226
  - test/test_helper.rb
@@ -244,7 +247,7 @@ homepage: http://github.com/cloudwalkio/da_funk
244
247
  licenses:
245
248
  - MIT
246
249
  metadata: {}
247
- post_install_message:
250
+ post_install_message:
248
251
  rdoc_options: []
249
252
  require_paths:
250
253
  - lib
@@ -259,8 +262,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
259
262
  - !ruby/object:Gem::Version
260
263
  version: '0'
261
264
  requirements: []
262
- rubygems_version: 3.1.2
263
- signing_key:
265
+ rubygems_version: 3.0.0
266
+ signing_key:
264
267
  specification_version: 4
265
268
  summary: MRuby Embedded System Framework
266
269
  test_files:
@@ -268,6 +271,9 @@ test_files:
268
271
  - test/integration/mrb_eval_test.rb
269
272
  - test/integration/notification_test.rb
270
273
  - test/integration/params_dat_test.rb
274
+ - test/iso8583/bitmap_test.rb
275
+ - test/iso8583/message_test.rb
276
+ - test/iso8583/minitest_helper.rb
271
277
  - test/resources/shared/bitmap.dat
272
278
  - test/resources/shared/bitmap_gp.dat
273
279
  - test/test_helper.rb