bitstring 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (55) hide show
  1. data/CONTRIBUTORS.txt +5 -0
  2. data/Changelog.txt +20 -0
  3. data/LICENCE.txt +202 -0
  4. data/NOTICE.txt +5 -0
  5. data/README.txt +63 -0
  6. data/doc/classes/BitString.html +2479 -0
  7. data/doc/classes/BitString.src/M000001.html +99 -0
  8. data/doc/classes/BitString.src/M000002.html +18 -0
  9. data/doc/classes/BitString.src/M000003.html +20 -0
  10. data/doc/classes/BitString.src/M000004.html +19 -0
  11. data/doc/classes/BitString.src/M000005.html +24 -0
  12. data/doc/classes/BitString.src/M000006.html +44 -0
  13. data/doc/classes/BitString.src/M000007.html +21 -0
  14. data/doc/classes/BitString.src/M000008.html +18 -0
  15. data/doc/classes/BitString.src/M000009.html +18 -0
  16. data/doc/classes/BitString.src/M000010.html +22 -0
  17. data/doc/classes/BitString.src/M000011.html +29 -0
  18. data/doc/classes/BitString.src/M000012.html +22 -0
  19. data/doc/classes/BitString.src/M000013.html +43 -0
  20. data/doc/classes/BitString.src/M000014.html +19 -0
  21. data/doc/classes/BitString.src/M000015.html +40 -0
  22. data/doc/classes/BitString.src/M000016.html +21 -0
  23. data/doc/classes/BitString.src/M000017.html +18 -0
  24. data/doc/classes/BitString.src/M000018.html +18 -0
  25. data/doc/classes/BitString.src/M000019.html +18 -0
  26. data/doc/classes/BitString.src/M000020.html +20 -0
  27. data/doc/classes/BitString.src/M000021.html +24 -0
  28. data/doc/classes/BitString.src/M000022.html +23 -0
  29. data/doc/classes/BitString.src/M000023.html +42 -0
  30. data/doc/classes/BitString.src/M000024.html +61 -0
  31. data/doc/classes/BitString.src/M000025.html +18 -0
  32. data/doc/classes/BitString.src/M000026.html +18 -0
  33. data/doc/classes/BitString.src/M000027.html +20 -0
  34. data/doc/classes/BitString.src/M000028.html +18 -0
  35. data/doc/classes/BitString.src/M000029.html +18 -0
  36. data/doc/classes/BitString.src/M000030.html +18 -0
  37. data/doc/classes/BitString.src/M000031.html +18 -0
  38. data/doc/classes/BitString.src/M000032.html +18 -0
  39. data/doc/created.rid +1 -0
  40. data/doc/files/lib/bitstring/operators_rb.html +122 -0
  41. data/doc/files/lib/bitstring_rb.html +153 -0
  42. data/doc/fr_class_index.html +27 -0
  43. data/doc/fr_file_index.html +28 -0
  44. data/doc/fr_method_index.html +60 -0
  45. data/doc/index.html +24 -0
  46. data/doc/rdoc-style.css +208 -0
  47. data/lib/bitstring.rb +1318 -0
  48. data/lib/bitstring/operators.rb +481 -0
  49. data/test/Rakefile +21 -0
  50. data/test/test_basic.rb +848 -0
  51. data/test/test_data.rb +24 -0
  52. data/test/test_enum.rb +671 -0
  53. data/test/test_helper.rb +3 -0
  54. data/test/test_operators.rb +454 -0
  55. metadata +121 -0
@@ -0,0 +1,21 @@
1
+ here = File.dirname(__FILE__) + '/'
2
+ libdir = File.expand_path(here + '../lib/')
3
+ $LOAD_PATH.unshift(libdir)
4
+
5
+ task :default => [ :test_basic, :test_operators, :test_enum ]
6
+
7
+ desc 'Test basic methods (construction, etc.)'
8
+ task :test_basic do
9
+ ruby "-I#{libdir} #{here}test_basic.rb"
10
+ end
11
+
12
+ desc 'Test operators (special characters, like & and |)'
13
+ task :test_operators do
14
+ ruby "-I#{libdir} #{here}test_operators.rb"
15
+ end
16
+
17
+ desc 'Test methods inherited from Enumerable mixin'
18
+ task :test_enum do
19
+ ruby "-I#{libdir} #{here}test_enum.rb"
20
+ end
21
+
@@ -0,0 +1,848 @@
1
+ require 'rubygems'
2
+ require File.dirname(__FILE__) + '/test_helper.rb'
3
+ require File.dirname(__FILE__) + '/test_data.rb'
4
+
5
+ #
6
+ # Test basic functionality, and non-operator methods we provide.
7
+ # (Other tests handle operators and the methods inherited from
8
+ # the Enumerable mixin.)
9
+ #
10
+
11
+ module Tests
12
+
13
+ class Test_BitStrings < Test::Unit::TestCase
14
+
15
+ #
16
+ # Just test creating the objects. We'll test whether they're valid
17
+ # later.
18
+ #
19
+ def test_000_construction()
20
+ TestVals.each do |sVal|
21
+ lVal = sVal.length
22
+ #
23
+ # Turn the binary string into an integer.
24
+ #
25
+ iVal = sVal.to_i(2)
26
+ #
27
+ # Reverse the string.
28
+ #
29
+ sVal_r = sVal.reverse
30
+ #
31
+ # Make an array of the digits as strings, and one of the digits as
32
+ # integers.
33
+ #
34
+ iVal_a = (sVal_a = sVal.split(//)).map { |bit| bit.to_i }
35
+ #
36
+ # Make reversed copies of those, too.
37
+ #
38
+ sVal_a_r = sVal_a.reverse
39
+ iVal_a_r = iVal_a.reverse
40
+
41
+ #
42
+ # Test making an unbounded string from the integer.
43
+ #
44
+ assert_nothing_raised("Test unbounded no exception new(#{iVal})") do
45
+ bs = BitString.new(iVal)
46
+ end
47
+
48
+ #
49
+ # From the string.
50
+ #
51
+ assert_nothing_raised("Test unbounded no exception new('#{sVal}')") do
52
+ bs = BitString.new(sVal)
53
+ end
54
+
55
+ #
56
+ # From the array of integers.
57
+ #
58
+ assert_nothing_raised("Test unbounded no exception new('#{iVal_a.inspect}')") do
59
+ bs = BitString.new(iVal_a)
60
+ end
61
+
62
+ #
63
+ # Try bounded now.
64
+ #
65
+ assert_nothing_raised("Test bounded no exception new(#{iVal})") do
66
+ bs = BitString.new(iVal, lVal)
67
+ end
68
+ assert_nothing_raised("Test bounded no exception new('#{sVal}')") do
69
+ bs = BitString.new(sVal, lVal)
70
+ end
71
+ assert_nothing_raised("Test bounded no exception new(#{iVal_a.inspect})") do
72
+ bs = BitString.new(iVal_a, lVal)
73
+ end
74
+
75
+ #
76
+ # Again, with lengths shorter than the values.
77
+ #
78
+ assert_nothing_raised("Test bounded no exception new(#{iVal} short)") do
79
+ bs = BitString.new(iVal, lVal / 2)
80
+ end
81
+ assert_nothing_raised("Test bounded no exception new('#{sVal}' short)") do
82
+ bs = BitString.new(sVal, lVal / 2)
83
+ end
84
+ assert_nothing_raised("Test bounded no exception new(#{iVal_a.inspect} short)") do
85
+ bs = BitString.new(iVal_a, lVal / 2)
86
+ end
87
+
88
+ #
89
+ # Now the block (bounded) form.
90
+ #
91
+ assert_nothing_raised("Test bounded new() {'#{sVal}'}") do
92
+ bs = BitString.new(lVal) { |bit| sVal_a_r[bit] }
93
+ end
94
+ assert_nothing_raised("Test bounded new() {#{iVal_a.inspect}}") do
95
+ bs = BitString.new(lVal) { |bit| iVal_a_r[bit] }
96
+ end
97
+
98
+ #
99
+ # Check that the constructor arguments are vetted.
100
+ #
101
+ input = 'a'
102
+ assert_raise(ArgumentError, "Test unbounded new(#{input.inspect})") do
103
+ bs = BitString.new(input)
104
+ end
105
+ input = iVal_a.collect { |v| v + 2 }
106
+ assert_raise(ArgumentError, "Test unbounded new(#{input.inspect})") do
107
+ bs = BitString.new(input)
108
+ end
109
+ input = iVal.to_s
110
+ unless (iVal < 2)
111
+ assert_raise(ArgumentError, "Test unbounded new(#{input.inspect})") do
112
+ bs = BitString.new(input)
113
+ end
114
+ assert_raise(ArgumentError, "Test bounded new(#{input.inspect})") do
115
+ bs = BitString.new(input, input.length)
116
+ end
117
+ end
118
+ input = 'a'
119
+ assert_raise(ArgumentError, "Test bounded new(#{input.inspect})") do
120
+ bs = BitString.new(input, 1)
121
+ end
122
+ assert_raise(ArgumentError, "Test bounded new(0, 'a')") do
123
+ bs = BitString.new(0, 'a')
124
+ end
125
+ end
126
+ end
127
+
128
+ #
129
+ # Test that conversion to an integer value works properly, since
130
+ # we depend on the to_i() method later in the tests.
131
+ #
132
+ def test_001_to_i()
133
+ TestVals.each do |sVal|
134
+ iVal = sVal.to_i(2)
135
+ bs = BitString.new(sVal)
136
+ assert_equal(iVal,
137
+ bs.to_i,
138
+ "Test BitString.to_i(#{sVal}) => #{iVal}")
139
+ end
140
+ end
141
+
142
+ #
143
+ # Test that conversion *from* an integer value works properly.
144
+ #
145
+ def test_002_from_i()
146
+ TestVals.each do |sVal|
147
+ iVal = sVal.to_i(2)
148
+ bs = BitString.new(0)
149
+ bs.from_i(iVal)
150
+ assert_equal(iVal,
151
+ bs.to_i,
152
+ "Test BitString.from_i(#{sVal}) => #{iVal}")
153
+ end
154
+ end
155
+
156
+ #
157
+ # Similarly, consider the to_s() method very early because we depend
158
+ # on it later.
159
+ #
160
+ def test_003_to_s()
161
+ TestVals.each do |sVal|
162
+ iVal = sVal.to_i(2)
163
+ sVal_e = sVal.sub(/^0+(.)/, '\1')
164
+ bs = BitString.new(sVal)
165
+ assert_equal(sVal_e,
166
+ bs.to_s,
167
+ "Test unbounded '#{sVal}'.to_s => '#{sVal_e}'")
168
+ bs = BitString.new(sVal, sVal.length)
169
+ assert_equal(sVal,
170
+ bs.to_s,
171
+ "Test bounded '#{sVal}'.to_s => '#{sVal}'")
172
+ end
173
+ end
174
+
175
+ #
176
+ # The length() method is pretty important, too.
177
+ #
178
+ def test_004_length()
179
+ TestVals.each do |sVal|
180
+ #
181
+ # The length() method returns either the size of a bounded
182
+ # bitstring, or the number of digits from the most significant
183
+ # 1.
184
+ #
185
+ uLength = sVal.sub(/^0+(.)/, '\1').length
186
+ bLength = sVal.length
187
+ bs = BitString.new(sVal)
188
+ assert_equal(uLength,
189
+ bs.length,
190
+ "Test unbounded '#{sVal}'.length => #{uLength}")
191
+ #
192
+ # Now do the same check for the bounded version.
193
+ #
194
+ bs = BitString.new(sVal, sVal.length)
195
+ bLength = sVal.length
196
+ assert_equal(bLength,
197
+ bs.length,
198
+ "Test bounded '#{sVal}'.length => #{bLength}")
199
+ end
200
+ end
201
+
202
+ #
203
+ # Test that string are being properly marked as bounded -- or not.
204
+ #
205
+ def test_005_bounded?()
206
+ TestVals.each do |sVal|
207
+ bs = BitString.new(sVal)
208
+ assert(! bs.bounded?)
209
+ bs = BitString.new(sVal, sVal.length)
210
+ assert(bs.bounded?)
211
+ bs = BitString.new(sVal.length) { |i| sVal.reverse[i,1].to_i }
212
+ assert(bs.bounded?)
213
+ end
214
+ end
215
+
216
+ #
217
+ # Test the clear() and clear!() methods.
218
+ #
219
+ def test_006_clear()
220
+ TestVals.each do |sVal|
221
+ bs = BitString.new(sVal)
222
+ tbs = bs.clear
223
+ assert_equal(sVal.to_i(2),
224
+ bs.to_i,
225
+ "Test that '#{sVal}'.clear() leaves original set")
226
+ assert_equal(0,
227
+ tbs.to_i,
228
+ "Test that '#{sVal}'.clear() returns cleared bitstring")
229
+ bs.clear!
230
+ assert_equal(0,
231
+ bs.to_i,
232
+ "Test that '#{sVal}'.clear!() clears original bitstring")
233
+ end
234
+ end # def test_006_clear()
235
+
236
+ #
237
+ # Indexed access is critically important, so we test its permutations
238
+ # here rather in the 'operators' test set.
239
+ #
240
+
241
+ #
242
+ # Try simple single-bit accesses through the [] method.
243
+ #
244
+ def test_007_indexing()
245
+ TestVals.each do |sVal|
246
+ lVal = sVal.length
247
+ iVal_a_r = sVal.reverse.split(//).map { |bit| bit.to_i }
248
+ bs = BitString.new(sVal)
249
+ #
250
+ # Let's try fetching each bit.
251
+ #
252
+ lVal.times do |i|
253
+ assert_equal(iVal_a_r[i],
254
+ bs[i],
255
+ "Test fetching index [#{i}] => #{iVal_a_r[i]}")
256
+ end
257
+
258
+ #
259
+ # Try setting each bit to its value.
260
+ #
261
+ bs = BitString.new(sVal)
262
+ lVal.times do |i|
263
+ bs[i] = iVal_a_r[i]
264
+ assert_equal(iVal_a_r[i],
265
+ bs[i],
266
+ "Test setting bit to itself " +
267
+ "[#{i}] = #{iVal_a_r[i]}; [#{i}] => #{iVal_a_r[i]}")
268
+ end
269
+
270
+ #
271
+ # Try setting each bit to its complement.
272
+ #
273
+ bs = BitString.new(sVal)
274
+ lVal.times do |i|
275
+ pre = bs.to_s
276
+ bs[i] = ~ bs[i]
277
+ post = bs.to_s
278
+ assert_not_equal(iVal_a_r[i],
279
+ bs[i],
280
+ "Test setting bit to its complement " +
281
+ "[#{i}] = ~[#{i}] != #{iVal_a_r[i]}\n" +
282
+ "pre=[#{pre}] post=[#{post}] sVal=[#{sVal}]")
283
+ end
284
+
285
+ #
286
+ # Try fetching with indices beyond the bounds.
287
+ #
288
+ msg = "Test no exception from unbounded '#{sVal}'[#{lVal + 10}]"
289
+ assert_nothing_raised(msg) do
290
+ bs[lVal + 10]
291
+ end
292
+ msg = "Test IndexError exception from unbounded '#{sVal}'[-1]"
293
+ assert_raise(IndexError, msg) do
294
+ bs[-1]
295
+ end
296
+ bs = BitString.new(sVal, lVal)
297
+ msg = "Test IndexError exception from bounded '#{sVal}'[#{lVal + 10}]"
298
+ assert_raise(IndexError, msg) do
299
+ bs[lVal + 10]
300
+ end
301
+ msg = "Test IndexError exception from bounded '#{sVal}'[-1]"
302
+ assert_raise(IndexError, msg) do
303
+ bs[-1]
304
+ end
305
+ end
306
+ end
307
+
308
+ #
309
+ # Now let's try ranges for indexing. First, use [start..end] syntax.
310
+ #
311
+ def test_008_ranges()
312
+ TestVals.each do |sVal|
313
+ length = sVal.length
314
+ (length - 2).times do |width|
315
+ width += 2
316
+ bs = BitString.new(sVal)
317
+ #
318
+ # Test subranging n bits at a time in a fetch
319
+ #
320
+ (length - width + 1).times do |i|
321
+ excerpt = sVal[length-width-i,width].to_i(2)
322
+ rng = i..i+width-1
323
+ assert_equal(excerpt,
324
+ bs[rng].to_i,
325
+ 'Test fetching bitstring subrange ' +
326
+ "'#{bs.to_s}'[#{rng}] => '#{excerpt}'\n" +
327
+ "(sVal='#{sVal}', length=#{length}, " +
328
+ "width=#{width}, i=#{i})")
329
+ end
330
+ #
331
+ # Now try setting that range to its complement
332
+ #
333
+ (length - width + 1).times do |i|
334
+ bs = BitString.new(sVal)
335
+ excerpt = (~ sVal[length-width-i,width].to_i(2)) & (2**width - 1)
336
+ rng = i..i+width-1
337
+ bs[rng] = excerpt
338
+ assert_equal(excerpt,
339
+ bs[rng].to_i,
340
+ 'Test bitstring subrange after set' +
341
+ "'#{bs.to_s}'[#{rng}] => '#{excerpt}'")
342
+ end
343
+
344
+ #
345
+ # Now do the same with a bounded bitstring.
346
+ #
347
+ bs = BitString.new(sVal, length)
348
+ #
349
+ # Test subranging n bits at a time in a fetch
350
+ #
351
+ (length - width + 1).times do |i|
352
+ excerpt = sVal[length-width-i,width].to_i(2)
353
+ rng = i..i+width-1
354
+ assert_equal(excerpt,
355
+ bs[rng].to_i,
356
+ 'Test fetching bitstring subrange ' +
357
+ "'#{bs.to_s}'[#{rng}] => '#{excerpt}'\n" +
358
+ "(sVal='#{sVal}', length=#{length}, " +
359
+ "width=#{width}, i=#{i})")
360
+ end
361
+ #
362
+ # Now try setting that range to its complement
363
+ #
364
+ (length - width + 1).times do |i|
365
+ bs = BitString.new(sVal, length)
366
+ excerpt = (~ sVal[length-width-i,width].to_i(2)) & (2**width - 1)
367
+ rng = i..i+width-1
368
+ bs[rng] = excerpt
369
+ assert_equal(excerpt,
370
+ bs[rng].to_i,
371
+ 'Test bitstring subrange after set' +
372
+ "'#{bs.to_s}'[#{rng}] => '#{excerpt}'")
373
+ end
374
+ end
375
+ end
376
+ end
377
+
378
+ #
379
+ # Now try the [start,count] format.
380
+ #
381
+ def test_009_ranges()
382
+ TestVals.each do |sVal|
383
+ bs = BitString.new(sVal)
384
+ length = sVal.length
385
+ (length - 2).times do |width|
386
+ width += 2
387
+ #
388
+ # Test subranging n bits at a time
389
+ #
390
+ (length - width + 1).times do |i|
391
+ excerpt = sVal[length-width-i,width].to_i(2)
392
+ assert_equal(excerpt,
393
+ bs[i,width].to_i,
394
+ 'Test bitstring subrange ' +
395
+ "'#{bs.to_s}'[#{i},#{width}] =>'#{excerpt}'")
396
+ end
397
+ end
398
+ end
399
+ end
400
+
401
+ #
402
+ # Verify that the 'least significant bit' method is returning the
403
+ # right value.
404
+ #
405
+ def test_010_lsb()
406
+ TestVals.each do |sVal|
407
+ iVal = sVal.to_i(2)
408
+ bs = BitString.new(sVal)
409
+ assert_equal(sVal[-1,1].to_i(2),
410
+ bs.lsb,
411
+ "Test lsb(#{sVal}) => #{sVal[-1,1].to_i(2)}")
412
+ end
413
+ end
414
+
415
+ #
416
+ # Test the msb (most significant bit) method, which only works on
417
+ # bounded strings.
418
+ #
419
+ def test_011_msb()
420
+ TestVals.each do |sVal|
421
+ bs = BitString.new(sVal)
422
+ msg = "Test RuntimeError raised by unbounded msb()"
423
+ assert_raise(RuntimeError, msg) do
424
+ bs.msb
425
+ end
426
+ bs = BitString.new(sVal, sVal.length)
427
+ assert_equal(sVal[0,1].to_i,
428
+ bs.msb,
429
+ "Test bounded msb(#{sVal}) => #{sVal[0,1].to_i}")
430
+ end
431
+ end
432
+
433
+ #
434
+ # Test growing the bit string, in either direction.
435
+ #
436
+ def test_012_grow()
437
+ nBits = 10
438
+ TestVals.each do |sVal|
439
+ bs = BitString.new(sVal)
440
+ msg = "Test IndexError raised for unbounded grow(#{-nBits})"
441
+ assert_raise(IndexError, msg) do
442
+ bs.grow(-nBits)
443
+ end
444
+ msg = "Test IndexError raised for unbounded grow!(#{-nBits})"
445
+ assert_raise(IndexError, msg) do
446
+ bs.grow!(-nBits)
447
+ end
448
+ msg = "Test RuntimeError raised for unbounded grow(#{nBits})"
449
+ assert_raise(RuntimeError, msg) do
450
+ bs.grow(nBits)
451
+ end
452
+ msg = "Test RuntimeError raised for unbounded grow!(#{nBits})"
453
+ assert_raise(RuntimeError) do
454
+ bs.grow!(nBits)
455
+ end
456
+
457
+ #
458
+ # Loop for the default value.
459
+ #
460
+ [ nil, 0, 1 ].each do |defval|
461
+ bcmd = "bs.grow(#{nBits}"
462
+ bcmd += ", #{defval}" unless (defval.nil?)
463
+ [ nil, 'BitString::HIGH_END', 'BitString::LOW_END' ].each do |dir|
464
+ dir = nil if (defval.nil?)
465
+ cmd = bcmd
466
+ cmd += ", #{dir}" unless (dir.nil?)
467
+ cmd += ')'
468
+ idir = dir
469
+ eval("idir = #{dir}") unless (dir.nil?)
470
+ #
471
+ # Create the base bitstring, and then get the grown copy
472
+ #
473
+ bs = BitString.new(sVal, sVal.length)
474
+ tbs = eval(cmd)
475
+ cmd2 = cmd.sub(/(grow)\(/, '\1!(')
476
+ eval(cmd2)
477
+ cmd.sub!(/^bs/, '')
478
+ cmd2.sub!(/^bs/, '')
479
+ assert_equal(sVal.length + nBits,
480
+ tbs.length,
481
+ "Test '#{sVal}'#{cmd}.length (#{tbs.to_s})")
482
+ assert_equal(sVal.length + nBits,
483
+ bs.length,
484
+ "Test '#{sVal}'#{cmd2}.length (#{bs.to_s})")
485
+ if ((defval.nil? && idir.nil?) ||
486
+ ((defval == 0) &&
487
+ (idir.nil? || (idir == BitString::HIGH_END))))
488
+ #
489
+ # grow(nBits)
490
+ # grow(nBits, 0)
491
+ # grow(nBits, 0, BitString::HIGH_END)
492
+ #
493
+ assert_equal(0,
494
+ tbs[sVal.length,nBits].to_i,
495
+ "Test '#{sVal}'#{cmd} fills high 0 (#{tbs.to_s})")
496
+ assert_equal(0,
497
+ bs[sVal.length,nBits].to_i,
498
+ "Test '#{sVal}'#{cmd2} fills high 0 " +
499
+ "(#{tbs.to_s})")
500
+
501
+ assert_equal(0,
502
+ tbs[sVal.length,nBits].to_i,
503
+ "Test '#{sVal}'#{cmd} fills high 0 (#{tbs.to_s})")
504
+ assert_equal(0,
505
+ bs[sVal.length,nBits].to_i,
506
+ "Test '#{sVal}'#{cmd2} fills high 0 (#{bs.to_s})")
507
+ elsif ((defval == 1) &&
508
+ (idir.nil? || (idir == BitString::HIGH_END)))
509
+ #
510
+ # grow(nBits, 1)
511
+ # grow(nBits, 1, BitString::HIGH_END)
512
+ #
513
+ assert_equal(2**nBits - 1,
514
+ tbs[sVal.length,nBits].to_i,
515
+ "Test '#{sVal}'#{cmd} fills high 1 (#{tbs.to_s})")
516
+ assert_equal(2**nBits - 1,
517
+ bs[sVal.length,nBits].to_i,
518
+ "Test '#{sVal}'#{cmd2} fills high 1 (#{bs.to_s})")
519
+ elsif ((defval == 0) && (idir == BitString::LOW_END))
520
+ #
521
+ # grow(nBits, 0, BitString::LOW_END)
522
+ #
523
+ assert_equal(0,
524
+ tbs[0,nBits].to_i,
525
+ "Test '#{sVal}'#{cmd} fills low 0 (#{tbs.to_s})")
526
+ assert_equal(0,
527
+ bs[0,nBits].to_i,
528
+ "Test '#{sVal}'#{cmd2} fills low 0 (#{bs.to_s})")
529
+
530
+ assert_equal(sVal.to_i(2),
531
+ tbs[nBits,sVal.length].to_i,
532
+ "Test '#{sVal}'#{cmd} properly shifts and " +
533
+ "low fills 0 (#{tbs.to_s})")
534
+ assert_equal(sVal.to_i(2),
535
+ bs[nBits,sVal.length].to_i,
536
+ "Test '#{sVal}'#{cmd2} properly shifts and " +
537
+ "low fills 0 (#{bs.to_s})")
538
+ elsif ((defval == 1) && (idir == BitString::LOW_END))
539
+ #
540
+ # grow(nBits, 1, BitString::LOW_END)
541
+ #
542
+ assert_equal(2**nBits - 1,
543
+ tbs[0,nBits].to_i,
544
+ "Test '#{sVal}'#{cmd} fills low 1 (#{tbs.to_s})")
545
+ assert_equal(2**nBits - 1,
546
+ bs[0,nBits].to_i,
547
+ "Test '#{sVal}'#{cmd2} fills low 1 (#{bs.to_s})")
548
+
549
+ assert_equal(sVal.to_i(2),
550
+ tbs[nBits,sVal.length].to_i,
551
+ "Test '#{sVal}'#{cmd} properly shifts and " +
552
+ "low fills 1 (#{tbs.to_s})")
553
+ assert_equal(sVal.to_i(2),
554
+ bs[nBits,sVal.length].to_i,
555
+ "Test '#{sVal}'#{cmd2} properly shifts and " +
556
+ "low fills 1 (#{bs.to_s})")
557
+ else
558
+ assert(false, "Missed case '#{sVal}'#{cmd}\n" +
559
+ "sVal=#{tbs.to_s}\n" +
560
+ "defval=#{defval.inspect}\n" +
561
+ "dir=#{dir.inspect}")
562
+ end
563
+ end
564
+ end
565
+ end
566
+ end
567
+
568
+ #
569
+ # Test shrinking the bitstring (making it shorter).
570
+ #
571
+ def test_013_shrink()
572
+ TestVals.each do |sVal|
573
+ nBits = [9, sVal.length].min + 1
574
+ bs = BitString.new(sVal)
575
+ assert_raise(IndexError) do
576
+ bs.shrink(-nBits)
577
+ end
578
+ assert_raise(IndexError) do
579
+ bs.shrink!(-nBits)
580
+ end
581
+ assert_raise(RuntimeError) do
582
+ bs.shrink(nBits)
583
+ end
584
+ assert_raise(RuntimeError) do
585
+ bs.shrink!(nBits)
586
+ end
587
+ bs = BitString.new(sVal, sVal.length)
588
+ assert_raise(RuntimeError) do
589
+ bs.shrink(sVal.length)
590
+ end
591
+ assert_raise(RuntimeError) do
592
+ bs.shrink!(sVal.length)
593
+ end
594
+
595
+ #
596
+ # Loop for the default value.
597
+ #
598
+ [ nil, 0, 1 ].each do |defval|
599
+ bcmd = "bs.shrink(#{nBits}"
600
+ [ nil, 'BitString::HIGH_END', 'BitString::LOW_END' ].each do |dir|
601
+ cmd = bcmd
602
+ cmd += ", #{dir}" unless (dir.nil?)
603
+ cmd += ')'
604
+ idir = dir
605
+ eval("idir = #{dir}") unless (dir.nil?)
606
+ #
607
+ # Create the base bitstring, and then get the shrunken copy
608
+ #
609
+ bs = BitString.new(sVal, sVal.length)
610
+ tbs = eval(cmd)
611
+ cmd2 = cmd.sub(/(shrink)\(/, '\1!(')
612
+ eval(cmd2)
613
+ cmd.sub!(/^bs/, '')
614
+ cmd2.sub!(/^bs/, '')
615
+ assert_equal(sVal.length - nBits,
616
+ tbs.length,
617
+ "Test '#{sVal}'#{cmd}.length (#{tbs.to_s})")
618
+ assert_equal(sVal.length - nBits,
619
+ bs.length,
620
+ "Test '#{sVal}'#{cmd2}.length (#{bs.to_s})")
621
+ newLength = sVal.length - nBits
622
+ if (idir.nil? || (idir == BitString::HIGH_END))
623
+ #
624
+ # shrink(nBits)
625
+ # shrink(nBits, BitString::HIGH_END)
626
+ #
627
+ assert_equal(sVal[nBits,newLength].to_i(2),
628
+ tbs.to_i,
629
+ "Test '#{sVal}'#{cmd} properly truncates " +
630
+ "high (#{tbs.to_s})")
631
+ assert_equal(sVal[nBits,newLength].to_i(2),
632
+ bs.to_i,
633
+ "Test '#{sVal}'#{cmd2} properly truncates " +
634
+ "high (#{bs.to_s})")
635
+
636
+ elsif (idir == BitString::LOW_END)
637
+ #
638
+ # shrink(nBits, BitString::LOW_END)
639
+ #
640
+ assert_equal(sVal[0,newLength].to_i(2),
641
+ tbs.to_i,
642
+ "Test '#{sVal}'#{cmd} properly shifts " +
643
+ "low (#{tbs.to_s})")
644
+ assert_equal(sVal[0,newLength].to_i(2),
645
+ bs.to_i,
646
+ "Test '#{sVal}'#{cmd2} properly shifts " +
647
+ "low (#{bs.to_s})")
648
+ else
649
+ assert(false, "Missed case '#{sVal}'#{cmd}\n" +
650
+ "sVal=#{tbs.to_s}\n" +
651
+ "dir=#{dir.inspect}")
652
+ end
653
+ end
654
+ end
655
+ end
656
+ end
657
+
658
+ #
659
+ # Try resizing bitstrings.
660
+ #
661
+ def test_014_resize()
662
+ assert_raise(IndexError, "Test resize(0) raises IndexError") do
663
+ bs = BitString.new(-1, 12)
664
+ bs.resize(0)
665
+ end
666
+ TestVals.each do |sVal|
667
+ #
668
+ # First off, test resizing unbounded bitstrings. The length()
669
+ # method returns the number of digits from the most significant
670
+ # 1. We should be able to resize up or down, and the result will
671
+ # be bounded.
672
+ #
673
+ bs = BitString.new(sVal)
674
+ oLength = bs.length
675
+ uLength = sVal.sub(/^0+(.)/, '\1').length
676
+ #
677
+ # Resize down. Make sure we have at least 1 bit, since resizing
678
+ # to zero length raises an exception.
679
+ #
680
+ nBits = [9, [uLength / 2, 1].max].min
681
+ tbs = bs.resize(nBits)
682
+ assert_equal(oLength,
683
+ bs.length,
684
+ "Test that resize original stays the same length")
685
+ assert(tbs.bounded?,
686
+ "Test that new downsized bitstring is bounded")
687
+ assert_equal(nBits,
688
+ tbs.length,
689
+ "Test '#{sVal}'.resize(#{nBits} => '#{tbs.to_s}'.length")
690
+ bs.resize!(nBits)
691
+ assert(bs.bounded?, "Test that downsized bitstring is bounded")
692
+ assert_equal(nBits,
693
+ bs.length,
694
+ "Test '#{sVal}'.resize(#{nBits} => '#{bs.to_s}'.length")
695
+
696
+ #
697
+ # Resize up.
698
+ #
699
+ bs = BitString.new(sVal, sVal.length)
700
+ oLength = bs.length
701
+ nBits = uLength * 2
702
+ tbs = bs.resize(nBits)
703
+ assert_equal(oLength,
704
+ bs.length,
705
+ "Test that resize original stays the same length")
706
+ assert(tbs.bounded?, "Test that new upsized bitstring is bounded")
707
+ assert_equal(nBits,
708
+ tbs.length,
709
+ "Test '#{sVal}'.resize(#{nBits} => '#{tbs.to_s}'.length")
710
+ bs.resize!(nBits)
711
+ assert(bs.bounded?, "Test that upsized bitstring is bounded")
712
+ assert_equal(nBits,
713
+ bs.length,
714
+ "Test '#{sVal}'.resize(#{nBits} => '#{bs.to_s}'.length")
715
+ end
716
+ end
717
+
718
+ #
719
+ # Test rotating bitstrings (only works for bounded ones).
720
+ #
721
+ def test_015_rotate()
722
+ bs = BitString.new('1001010010101110001101')
723
+ msg = "Test RuntimeError raised for unbounded rotate(10)"
724
+ assert_raise(RuntimeError, msg) do
725
+ tbs = bs.rotate(10)
726
+ end
727
+ msg = "Test RuntimeError raised for unbounded rotate!(10)"
728
+ assert_raise(RuntimeError, msg) do
729
+ bs.rotate!(10)
730
+ end
731
+ TestVals.each do |sVal|
732
+ lVal = sVal.length
733
+ 100.times do |i|
734
+ bs = BitString.new(sVal, lVal)
735
+ tBits = rand(lVal * (rand(5) + 1))
736
+ nBits = tBits % lVal
737
+ sign = rand(100) < 50 ? -1 : 1
738
+ if (sign < 0)
739
+ #
740
+ # Rotating left
741
+ #
742
+ nsVal = sVal[nBits,lVal-nBits] + sVal[0,nBits]
743
+ else
744
+ #
745
+ # Rotating right.
746
+ #
747
+ nsVal = sVal[lVal-nBits,nBits] + sVal[0,lVal-nBits]
748
+ end
749
+ tbs = bs.rotate(tBits * sign)
750
+ assert_equal(sVal,
751
+ bs.to_s,
752
+ "Test that rotate(#{tBits * sign}) " +
753
+ "doesn't alter the source")
754
+ assert_equal(nsVal,
755
+ tbs.to_s,
756
+ "Test '#{sVal}'.rotate(#{tBits * sign}) => '#{nsVal}'")
757
+ bs.rotate!(tBits * sign)
758
+ assert_equal(nsVal,
759
+ bs.to_s,
760
+ "Test '#{sVal}'.rotate!(#{tBits * sign}) => '#{nsVal}'")
761
+ end
762
+ end
763
+ end
764
+
765
+ #
766
+ # Test the masking.
767
+ #
768
+ def test_017_mask()
769
+ TestVals.each do |sVal|
770
+ bs = BitString.new(sVal)
771
+ assert_raise(IndexError, "Test error on too many mask bits") do
772
+ bs.mask(bs.length + 2)
773
+ end
774
+ assert_raise(IndexError, "Test error on too many mask bits") do
775
+ bs.mask(bs.length + 2)
776
+ end
777
+ assert_equal(2**bs.length - 1,
778
+ bs.mask,
779
+ "Test unbounded full mask of '#{sVal}'")
780
+ bs = BitString.new(sVal, sVal.length)
781
+ assert_equal(2**bs.length - 1,
782
+ bs.mask,
783
+ "Test bounded full mask of '#{sVal}'")
784
+ end
785
+ end
786
+
787
+ #
788
+ # Test the each() method.
789
+ #
790
+ def test_018_each()
791
+ TestVals.each do |sVal|
792
+ bs = BitString.new(sVal)
793
+ pos = 0
794
+ bs.each do |val|
795
+ assert_equal(val,
796
+ bs[pos],
797
+ "Test unbounded each block(#{val}) (for #{pos})")
798
+ pos += 1
799
+ end
800
+ #
801
+ # And again for a bounded value.
802
+ #
803
+ bs = BitString.new(sVal, sVal.length)
804
+ pos = 0
805
+ bs.each do |val|
806
+ assert_equal(val,
807
+ bs[pos],
808
+ "Test bounded each block(#{val}) (for #{pos})")
809
+ pos += 1
810
+ end
811
+ end
812
+ end
813
+
814
+ #
815
+ # Test the bit-counting method.
816
+ #
817
+ def test_020_population()
818
+ TestVals.each do |sVal|
819
+ bs = BitString.new(sVal)
820
+ ones = sVal.gsub(/0/, '').length
821
+ zeroes = sVal.gsub(/^0+(.)/, '\1').gsub(/1/, '').length
822
+ assert_raise(ArgumentError, 'Test exception for population("a")') do
823
+ bs.population('a')
824
+ end
825
+ assert_equal(ones,
826
+ bs.population(1),
827
+ "Test unbounded '#{sVal}'.population(1)")
828
+ assert_equal(zeroes,
829
+ bs.population(0),
830
+ "Test unbounded '#{sVal}'.population(0)")
831
+ #
832
+ # Now bounded.
833
+ #
834
+ bs = BitString.new(sVal, sVal.length)
835
+ ones = sVal.gsub(/0/, '').length
836
+ zeroes = sVal.gsub(/1/, '').length
837
+ assert_equal(ones,
838
+ bs.population(1),
839
+ "Test bounded '#{sVal}'.population(1)")
840
+ assert_equal(zeroes,
841
+ bs.population(0),
842
+ "Test bounded '#{sVal}'.population(0)")
843
+ end
844
+ end
845
+
846
+ end
847
+
848
+ end # module Tests