bitstring 1.0.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 (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