da_funk 3.31.0 → 3.34.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (44) hide show
  1. checksums.yaml +4 -4
  2. data/Gemfile +10 -1
  3. data/Gemfile.lock +18 -8
  4. data/README.md +0 -0
  5. data/README_GUIDE.md +0 -0
  6. data/RELEASE_NOTES.md +22 -0
  7. data/Rakefile +14 -0
  8. data/guides/sample_input_output.rb +0 -0
  9. data/guides/sample_message_iso8583.rb +0 -0
  10. data/guides/sample_network_gprs.rb +0 -0
  11. data/guides/sample_read_magnect_card.rb +0 -0
  12. data/guides/sample_socket.rb +0 -0
  13. data/guides/sample_transaction.rb +0 -0
  14. data/guides/sample_transaction_download_application.rb +0 -0
  15. data/guides/sample_transaction_download_file.rb +0 -0
  16. data/guides/sample_transaction_download_parameter_file.rb +0 -0
  17. data/lib/da_funk/connection_management.rb +25 -10
  18. data/lib/da_funk/event_handler.rb +1 -1
  19. data/lib/da_funk/helper.rb +55 -16
  20. data/lib/da_funk/helper/status_bar.rb +42 -46
  21. data/lib/da_funk/params_dat.rb +65 -25
  22. data/lib/da_funk/transaction/download.rb +0 -0
  23. data/lib/da_funk/transaction/iso.rb +0 -0
  24. data/lib/da_funk/version.rb +1 -1
  25. data/lib/device.rb +0 -0
  26. data/lib/device/crypto.rb +0 -0
  27. data/lib/device/display.rb +0 -0
  28. data/lib/device/io.rb +53 -0
  29. data/lib/device/network.rb +19 -33
  30. data/lib/device/printer.rb +0 -0
  31. data/lib/device/setting.rb +0 -0
  32. data/lib/device/version.rb +0 -0
  33. data/lib/device/virtual_keyboard.rb +81 -34
  34. data/lib/file_db.rb +0 -0
  35. data/lib/iso8583/bitmap.rb +94 -54
  36. data/lib/iso8583/codec.rb +3 -3
  37. data/lib/iso8583/field.rb +48 -4
  38. data/lib/iso8583/fields.rb +3 -1
  39. data/lib/iso8583/message.rb +25 -12
  40. data/lib/iso8583/util.rb +1 -1
  41. data/test/iso8583/bitmap_test.rb +277 -0
  42. data/test/iso8583/message_test.rb +111 -0
  43. data/test/iso8583/minitest_helper.rb +11 -0
  44. metadata +12 -6
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
@@ -39,7 +39,7 @@ module ISO8583
39
39
  begin
40
40
  real_value = codec.decode(raw_value)
41
41
  rescue => e
42
- ContextLog.exception e, e.backtrace if Object.defined?(:ContextLog)
42
+ ContextLog.exception e, e.backtrace if Object.const_defined?(:ContextLog)
43
43
  raise ISO8583ParseException.new(e.message+" (#{name})")
44
44
  end
45
45
 
@@ -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,55 @@ 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
+ if @length.respond_to?(:odd?)
94
+ @data_length = @length
95
+ if @data_length.odd?
96
+ @byte_length = (@data_length + 1) / 2
97
+ else
98
+ @byte_length = @data_length / 2
99
+ end
100
+ return @byte_length
101
+ end
102
+ @length
103
+ end
104
+
105
+ def encode(value)
106
+ begin
107
+ encoded_value = codec.encode(value)
108
+ @data_length = value.size
109
+ @byte_length = encoded_value.bytes.size
110
+ rescue ISO8583Exception => e
111
+ ContextLog.exception(e, e.backtrace, "#{e.message} (#{name})") if Object.const_defined?(:ContextLog)
112
+ raise ISO8583Exception.new(e.message+" (#{name})")
113
+ end
114
+
115
+ if padding
116
+ if padding.arity == 1
117
+ encoded_value = padding.call(encoded_value)
118
+ elsif padding.arity == 2
119
+ encoded_value = padding.call(encoded_value, length)
120
+ end
121
+ end
122
+
123
+ len_str = case length
124
+ when Integer
125
+ raise ISO8583Exception.new("Too long: #{value} (#{name})! length=#{length}") if encoded_value.length > length
126
+ raise ISO8583Exception.new("Too short: #{value} (#{name})! length=#{length}") if encoded_value.length < length
127
+ String.new("", encoding: 'ASCII-8BIT')
128
+ when Field
129
+ raise ISO8583Exception.new("Max length exceeded: #{value}, max: #{max}") if max && @byte_length > max
130
+ length.encode(@data_length)
131
+ else
132
+ raise ISO8583Exception.new("Invalid length (#{length}) for '#{name}' field")
133
+ end
134
+
135
+ len_str + encoded_value
136
+
93
137
  end
94
138
  end
95
139
 
@@ -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