bindata 1.5.1 → 1.6.0

Sign up to get free protection for your applications and to get access to all the features.

Potentially problematic release.


This version of bindata might be problematic. Click here for more details.

Files changed (61) hide show
  1. data/ChangeLog.rdoc +7 -0
  2. data/NEWS.rdoc +11 -0
  3. data/Rakefile +6 -1
  4. data/bindata.gemspec +2 -1
  5. data/doc/manual.md +17 -9
  6. data/examples/gzip.rb +2 -2
  7. data/examples/list.rb +2 -2
  8. data/lib/bindata/alignment.rb +4 -9
  9. data/lib/bindata/array.rb +57 -51
  10. data/lib/bindata/base.rb +13 -110
  11. data/lib/bindata/base_primitive.rb +130 -75
  12. data/lib/bindata/bits.rb +5 -7
  13. data/lib/bindata/choice.rb +24 -32
  14. data/lib/bindata/dsl.rb +1 -6
  15. data/lib/bindata/framework.rb +81 -0
  16. data/lib/bindata/int.rb +5 -7
  17. data/lib/bindata/name.rb +28 -0
  18. data/lib/bindata/offset.rb +42 -53
  19. data/lib/bindata/params.rb +33 -38
  20. data/lib/bindata/struct.rb +2 -6
  21. data/lib/bindata/trace.rb +16 -16
  22. data/lib/bindata/version.rb +1 -1
  23. data/lib/bindata/virtual.rb +3 -3
  24. data/{spec/alignment_spec.rb → test/alignment_test.rb} +17 -16
  25. data/test/array_test.rb +371 -0
  26. data/test/base_primitive_test.rb +312 -0
  27. data/test/base_test.rb +183 -0
  28. data/{spec/bits_spec.rb → test/bits_test.rb} +59 -59
  29. data/test/choice_test.rb +260 -0
  30. data/{spec/spec_common.rb → test/common.rb} +33 -18
  31. data/test/count_bytes_remaining_test.rb +41 -0
  32. data/{spec/deprecated_spec.rb → test/deprecated_test.rb} +5 -7
  33. data/test/float_test.rb +72 -0
  34. data/{spec/int_spec.rb → test/int_test.rb} +34 -43
  35. data/{spec/io_spec.rb → test/io_test.rb} +70 -71
  36. data/{spec/lazy_spec.rb → test/lazy_test.rb} +38 -39
  37. data/test/offset_test.rb +93 -0
  38. data/test/params_test.rb +144 -0
  39. data/{spec/primitive_spec.rb → test/primitive_test.rb} +42 -54
  40. data/{spec/record_spec.rb → test/record_test.rb} +133 -154
  41. data/test/registry_test.rb +104 -0
  42. data/test/rest_test.rb +29 -0
  43. data/test/skip_test.rb +28 -0
  44. data/{spec/string_spec.rb → test/string_test.rb} +96 -97
  45. data/test/stringz_test.rb +127 -0
  46. data/{spec/struct_spec.rb → test/struct_test.rb} +119 -120
  47. data/{spec/system_spec.rb → test/system_test.rb} +66 -106
  48. metadata +39 -38
  49. data/lib/a.rb +0 -24
  50. data/spec/array_spec.rb +0 -331
  51. data/spec/base_primitive_spec.rb +0 -238
  52. data/spec/base_spec.rb +0 -376
  53. data/spec/choice_spec.rb +0 -263
  54. data/spec/count_bytes_remaining_spec.rb +0 -38
  55. data/spec/example.rb +0 -21
  56. data/spec/float_spec.rb +0 -37
  57. data/spec/registry_spec.rb +0 -108
  58. data/spec/rest_spec.rb +0 -26
  59. data/spec/skip_spec.rb +0 -27
  60. data/spec/stringz_spec.rb +0 -118
  61. data/tasks/rspec.rake +0 -17
@@ -0,0 +1,371 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require File.expand_path(File.join(File.dirname(__FILE__), "common"))
4
+
5
+ describe BinData::Array, "when instantiating" do
6
+ describe "with no mandatory parameters supplied" do
7
+ it "raises an error" do
8
+ args = {}
9
+ lambda { BinData::Array.new(args) }.must_raise ArgumentError
10
+ end
11
+ end
12
+
13
+ describe "with some but not all mandatory parameters supplied" do
14
+ it "raises an error" do
15
+ args = {:initial_length => 3}
16
+ lambda { BinData::Array.new(args) }.must_raise ArgumentError
17
+ end
18
+ end
19
+
20
+ it "fails if a given type is unknown" do
21
+ args = {:type => :does_not_exist, :initial_length => 3}
22
+ lambda { BinData::Array.new(args) }.must_raise BinData::UnRegisteredTypeError
23
+ end
24
+
25
+ it "does not allow both :initial_length and :read_until" do
26
+ args = {:initial_length => 3, :read_until => lambda { false } }
27
+ lambda { BinData::Array.new(args) }.must_raise ArgumentError
28
+ end
29
+
30
+ it "accepts BinData::Base as :type" do
31
+ obj = BinData::Int8.new(:initial_value => 5)
32
+ array = BinData::Array.new(:type => obj, :initial_length => 1)
33
+ array.must_equal [5]
34
+ end
35
+ end
36
+
37
+ describe BinData::Array, "with no elements" do
38
+ let(:obj) { BinData::Array.new(:type => :example_single) }
39
+
40
+ it "initial state" do
41
+ assert obj.clear?
42
+ obj.must_be_empty
43
+ obj.length.must_equal 0
44
+ obj.first.must_be_nil
45
+ obj.last.must_be_nil
46
+ end
47
+
48
+ it "returns [] for the first n elements" do
49
+ obj.first(3).must_equal []
50
+ end
51
+
52
+ it "returns [] for the last n elements" do
53
+ obj.last(3).must_equal []
54
+ end
55
+ end
56
+
57
+ describe BinData::Array, "with several elements" do
58
+ let(:obj) {
59
+ type = [:example_single, {:initial_value => lambda { index + 1 }}]
60
+ BinData::Array.new(:type => type, :initial_length => 5)
61
+ }
62
+
63
+ it "initial state" do
64
+ assert obj.clear?
65
+ obj.wont_be_empty
66
+ obj.size.must_equal 5
67
+ obj.length.must_equal 5
68
+ obj.snapshot.must_equal [1, 2, 3, 4, 5]
69
+ obj.inspect.must_equal "[1, 2, 3, 4, 5]"
70
+ end
71
+
72
+ it "coerces to ::Array if required" do
73
+ [0].concat(obj).must_equal [0, 1, 2, 3, 4, 5]
74
+ end
75
+
76
+ it "uses methods from Enumerable" do
77
+ obj.select { |x| (x % 2) == 0 }.must_equal [2, 4]
78
+ end
79
+
80
+ it "assigns primitive values" do
81
+ obj.assign([4, 5, 6])
82
+ obj.must_equal [4, 5, 6]
83
+ end
84
+
85
+ it "assigns bindata objects" do
86
+ obj.assign([ExampleSingle.new(4), ExampleSingle.new(5), ExampleSingle.new(6)])
87
+ obj.must_equal [4, 5, 6]
88
+ end
89
+
90
+ it "assigns a bindata array" do
91
+ array = BinData::Array.new([4, 5, 6], :type => :example_single)
92
+ obj.assign(array)
93
+ obj.must_equal [4, 5, 6]
94
+ end
95
+
96
+ it "returns the first element" do
97
+ obj.first.must_equal 1
98
+ end
99
+
100
+ it "returns the first n elements" do
101
+ obj[0...3].must_equal [1, 2, 3]
102
+ obj.first(3).must_equal [1, 2, 3]
103
+ obj.first(99).must_equal [1, 2, 3, 4, 5]
104
+ end
105
+
106
+ it "returns the last element" do
107
+ obj.last.must_equal 5
108
+ obj[-1].must_equal 5
109
+ end
110
+
111
+ it "returns the last n elements" do
112
+ obj.last(3).must_equal [3, 4, 5]
113
+ obj.last(99).must_equal [1, 2, 3, 4, 5]
114
+
115
+ obj[-3, 100].must_equal [3, 4, 5]
116
+ end
117
+
118
+ it "clears all" do
119
+ obj[1] = 8
120
+ obj.clear
121
+ obj.must_equal [1, 2, 3, 4, 5]
122
+ end
123
+
124
+ it "clears a single element" do
125
+ obj[1] = 8
126
+ obj[1].clear
127
+ obj[1].must_equal 2
128
+ end
129
+
130
+ it "is clear if all elements are clear" do
131
+ obj[1] = 8
132
+ obj[1].clear
133
+ assert obj.clear?
134
+ end
135
+
136
+ it "tests clear status of individual elements" do
137
+ obj[1] = 8
138
+ assert obj[0].clear?
139
+ refute obj[1].clear?
140
+ end
141
+
142
+ it "directly accesses elements" do
143
+ obj[1] = 8
144
+ obj[1].must_equal 8
145
+ end
146
+
147
+ it "symmetrically reads and writes" do
148
+ obj[1] = 8
149
+ str = obj.to_binary_s
150
+
151
+ obj.clear
152
+ obj[1].must_equal 2
153
+
154
+ obj.read(str)
155
+ obj[1].must_equal 8
156
+ end
157
+
158
+ it "identifies index of elements" do
159
+ obj.index(3).must_equal 2
160
+ end
161
+
162
+ it "returns nil for index of non existent element" do
163
+ obj.index(42).must_be_nil
164
+ end
165
+
166
+ it "has correct debug name" do
167
+ obj[2].debug_name.must_equal "obj[2]"
168
+ end
169
+
170
+ it "has correct offset" do
171
+ obj[2].offset.must_equal ExampleSingle.new.num_bytes * 2
172
+ end
173
+
174
+ it "has correct num_bytes" do
175
+ obj.num_bytes.must_equal 5 * ExampleSingle.new.num_bytes
176
+ end
177
+
178
+ it "has correct num_bytes for individual elements" do
179
+ obj[0].num_bytes.must_equal ExampleSingle.new.num_bytes
180
+ end
181
+ end
182
+
183
+ describe BinData::Array, "when accessing elements" do
184
+ let(:obj) {
185
+ type = [:example_single, {:initial_value => lambda { index + 1 }}]
186
+ data = BinData::Array.new(:type => type, :initial_length => 5)
187
+ data.assign([1, 2, 3, 4, 5])
188
+ data
189
+ }
190
+
191
+ it "inserts with positive indexes" do
192
+ obj.insert(2, 30, 40)
193
+ obj.snapshot.must_equal [1, 2, 30, 40, 3, 4, 5]
194
+ end
195
+
196
+ it "inserts with negative indexes" do
197
+ obj.insert(-2, 30, 40)
198
+ obj.snapshot.must_equal [1, 2, 3, 4, 30, 40, 5]
199
+ end
200
+
201
+ it "pushes" do
202
+ obj.push(30, 40)
203
+ obj.snapshot.must_equal [1, 2, 3, 4, 5, 30, 40]
204
+ end
205
+
206
+ it "concats" do
207
+ obj.concat([30, 40])
208
+ obj.snapshot.must_equal [1, 2, 3, 4, 5, 30, 40]
209
+ end
210
+
211
+ it "unshifts" do
212
+ obj.unshift(30, 40)
213
+ obj.snapshot.must_equal [30, 40, 1, 2, 3, 4, 5]
214
+ end
215
+
216
+ it "automatically extends on [index]" do
217
+ obj[9].must_equal 10
218
+ obj.snapshot.must_equal [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
219
+ end
220
+
221
+ it "automatically extends on []=" do
222
+ obj[9] = 30
223
+ obj.snapshot.must_equal [1, 2, 3, 4, 5, 6, 7, 8, 9, 30]
224
+ end
225
+
226
+ it "automatically extends on insert" do
227
+ obj.insert(7, 30, 40)
228
+ obj.snapshot.must_equal [1, 2, 3, 4, 5, 6, 7, 30, 40]
229
+ end
230
+
231
+ it "does not extend on at" do
232
+ obj.at(9).must_be_nil
233
+ obj.length.must_equal 5
234
+ end
235
+
236
+ it "does not extend on [start, length]" do
237
+ obj[9, 2].must_be_nil
238
+ obj.length.must_equal 5
239
+ end
240
+
241
+ it "does not extend on [range]" do
242
+ obj[9 .. 10].must_be_nil
243
+ obj.length.must_equal 5
244
+ end
245
+
246
+ it "raises error on bad input to []" do
247
+ lambda { obj["a"] }.must_raise TypeError
248
+ lambda { obj[1, "a"] }.must_raise TypeError
249
+ end
250
+ end
251
+
252
+ describe BinData::Array, "with :read_until" do
253
+
254
+ describe "containing +element+" do
255
+ it "reads until the sentinel is reached" do
256
+ read_until = lambda { element == 5 }
257
+ obj = BinData::Array.new(:type => :int8, :read_until => read_until)
258
+
259
+ obj.read "\x01\x02\x03\x04\x05\x06\x07\x08"
260
+ obj.must_equal [1, 2, 3, 4, 5]
261
+ end
262
+ end
263
+
264
+ describe "containing +array+ and +index+" do
265
+ it "reads until the sentinel is reached" do
266
+ read_until = lambda { index >= 2 and array[index - 2] == 5 }
267
+ obj = BinData::Array.new(:type => :int8, :read_until => read_until)
268
+
269
+ obj.read "\x01\x02\x03\x04\x05\x06\x07\x08"
270
+ obj.must_equal [1, 2, 3, 4, 5, 6, 7]
271
+ end
272
+ end
273
+
274
+ describe ":eof" do
275
+ it "reads records until eof" do
276
+ obj = BinData::Array.new(:type => :int8, :read_until => :eof)
277
+
278
+ obj.read "\x01\x02\x03"
279
+ obj.must_equal [1, 2, 3]
280
+ end
281
+
282
+ it "reads records until eof, ignoring partial records" do
283
+ obj = BinData::Array.new(:type => :int16be, :read_until => :eof)
284
+
285
+ obj.read "\x00\x01\x00\x02\x03"
286
+ obj.must_equal [1, 2]
287
+ end
288
+
289
+ it "reports exceptions" do
290
+ array_type = [:string, {:read_length => lambda { unknown_variable }}]
291
+ obj = BinData::Array.new(:type => array_type, :read_until => :eof)
292
+ lambda { obj.read "\x00\x01\x00\x02\x03" }.must_raise NoMethodError
293
+ end
294
+ end
295
+ end
296
+
297
+ describe BinData::Array, "nested within an Array" do
298
+ let(:obj) {
299
+ nested_array_params = { :type => [:int8, { :initial_value => :index }],
300
+ :initial_length => lambda { index + 1 } }
301
+ BinData::Array.new(:type => [:array, nested_array_params],
302
+ :initial_length => 3)
303
+ }
304
+
305
+ it "#snapshot" do
306
+ obj.snapshot.must_equal [ [0], [0, 1], [0, 1, 2] ]
307
+ end
308
+
309
+ it "maintains structure when reading" do
310
+ obj.read "\x04\x05\x06\x07\x08\x09"
311
+ obj.must_equal [ [4], [5, 6], [7, 8, 9] ]
312
+ end
313
+ end
314
+
315
+ describe BinData::Array, "subclassed" do
316
+ class IntArray < BinData::Array
317
+ endian :big
318
+ default_parameter :initial_element_value => 0
319
+
320
+ uint16 :initial_value => :initial_element_value
321
+ end
322
+
323
+ it "forwards parameters" do
324
+ obj = IntArray.new(:initial_length => 7)
325
+ obj.length.must_equal 7
326
+ end
327
+
328
+ it "overrides default parameters" do
329
+ obj = IntArray.new(:initial_length => 3, :initial_element_value => 5)
330
+ obj.to_binary_s.must_equal "\x00\x05\x00\x05\x00\x05"
331
+ end
332
+ end
333
+
334
+ describe BinData::Array, "of bits" do
335
+ let(:obj) { BinData::Array.new(:type => :bit1, :initial_length => 15) }
336
+
337
+ it "reads" do
338
+ str = [0b0001_0100, 0b1000_1000].pack("CC")
339
+ obj.read(str)
340
+ obj[0].must_equal 0
341
+ obj[1].must_equal 0
342
+ obj[2].must_equal 0
343
+ obj[3].must_equal 1
344
+ obj[4].must_equal 0
345
+ obj[5].must_equal 1
346
+ obj[6].must_equal 0
347
+ obj[7].must_equal 0
348
+ obj[8].must_equal 1
349
+ obj[9].must_equal 0
350
+ obj[10].must_equal 0
351
+ obj[11].must_equal 0
352
+ obj[12].must_equal 1
353
+ obj[13].must_equal 0
354
+ obj[14].must_equal 0
355
+ end
356
+
357
+ it "writes" do
358
+ obj[3] = 1
359
+ obj.to_binary_s.must_equal [0b0001_0000, 0b0000_0000].pack("CC")
360
+ end
361
+
362
+ it "returns num_bytes" do
363
+ obj.num_bytes.must_equal 2
364
+ end
365
+
366
+ it "has correct offset" do
367
+ obj[7].offset.must_equal 0
368
+ obj[8].offset.must_equal 1
369
+ end
370
+ end
371
+
@@ -0,0 +1,312 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require File.expand_path(File.join(File.dirname(__FILE__), "common"))
4
+
5
+ describe BinData::BasePrimitive do
6
+ it "is not registered" do
7
+ lambda {
8
+ BinData::RegisteredClasses.lookup("BasePrimitive")
9
+ }.must_raise BinData::UnRegisteredTypeError
10
+ end
11
+ end
12
+
13
+ describe BinData::BasePrimitive, "all subclasses" do
14
+ class SubClassOfBasePrimitive < BinData::BasePrimitive
15
+ expose_methods_for_testing
16
+ end
17
+
18
+ let(:obj) { SubClassOfBasePrimitive.new }
19
+
20
+ it "raise errors on unimplemented methods" do
21
+ lambda { obj.value_to_binary_string(nil) }.must_raise NotImplementedError
22
+ lambda { obj.read_and_return_value(nil) }.must_raise NotImplementedError
23
+ lambda { obj.sensible_default }.must_raise NotImplementedError
24
+ end
25
+ end
26
+
27
+ describe ExampleSingle do
28
+ let(:obj) { ExampleSingle.new(5) }
29
+
30
+ it "fails when assigning nil values" do
31
+ lambda { obj.assign(nil) }.must_raise ArgumentError
32
+ end
33
+
34
+ it "sets and retrieves values" do
35
+ obj.assign(7)
36
+ obj.must_equal 7
37
+ end
38
+
39
+ it "sets and retrieves BinData::BasePrimitives" do
40
+ obj.assign(ExampleSingle.new(7))
41
+ obj.must_equal 7
42
+ end
43
+
44
+ it "responds to known methods" do
45
+ obj.must_respond_to :num_bytes
46
+ end
47
+
48
+ it "responds to known methods in #snapshot" do
49
+ obj.must_respond_to :div
50
+ end
51
+
52
+ it "does not respond to unknown methods in self or #snapshot" do
53
+ obj.wont_respond_to :does_not_exist
54
+ end
55
+
56
+ it "behaves as #snapshot" do
57
+ (obj + 1).must_equal 6
58
+ (1 + obj).must_equal 6
59
+ end
60
+
61
+ it "is equal to other ExampleSingle" do
62
+ obj.must_equal ExampleSingle.new(5)
63
+ end
64
+
65
+ it "is equal to raw values" do
66
+ obj.must_equal 5
67
+ 5.must_equal obj
68
+ end
69
+
70
+ it "can be used as a hash key" do
71
+ hash = {5 => 17}
72
+
73
+ hash[obj].must_equal 17
74
+ end
75
+
76
+ it "is sortable" do
77
+ [ExampleSingle.new(5), ExampleSingle.new(3)].sort.must_equal [3, 5]
78
+ end
79
+ end
80
+
81
+ describe BinData::BasePrimitive, "after initialisation" do
82
+ let(:obj) { ExampleSingle.new }
83
+
84
+ it "does not allow both :initial_value and :value" do
85
+ params = {:initial_value => 1, :value => 2}
86
+ lambda { ExampleSingle.new(params) }.must_raise ArgumentError
87
+ end
88
+
89
+ it "initial state" do
90
+ assert obj.clear?
91
+ obj.value.must_equal 0
92
+ obj.num_bytes.must_equal 4
93
+ end
94
+
95
+ it "has symmetric IO" do
96
+ obj.assign(42)
97
+ written = obj.to_binary_s
98
+
99
+ ExampleSingle.read(written).must_equal 42
100
+ end
101
+
102
+ it "sets and retrieves values" do
103
+ obj.value = 5
104
+ obj.value.must_equal 5
105
+ end
106
+
107
+ it "is not clear after setting value" do
108
+ obj.assign(5)
109
+ refute obj.clear?
110
+ end
111
+
112
+ it "is not clear after reading" do
113
+ obj.read("\x11\x22\x33\x44")
114
+ refute obj.clear?
115
+ end
116
+
117
+ it "returns a snapshot" do
118
+ obj.assign(5)
119
+ obj.snapshot.must_equal 5
120
+ end
121
+ end
122
+
123
+ describe BinData::BasePrimitive, "with :initial_value" do
124
+ let(:obj) { ExampleSingle.new(:initial_value => 5) }
125
+
126
+ it "initial state" do
127
+ obj.value.must_equal 5
128
+ end
129
+
130
+ it "forgets :initial_value after being set" do
131
+ obj.assign(17)
132
+ obj.wont_equal 5
133
+ end
134
+
135
+ it "forgets :initial_value after reading" do
136
+ obj.read("\x11\x22\x33\x44")
137
+ obj.wont_equal 5
138
+ end
139
+
140
+ it "remembers :initial_value after being cleared" do
141
+ obj.assign(17)
142
+ obj.clear
143
+ obj.must_equal 5
144
+ end
145
+ end
146
+
147
+ describe BinData::BasePrimitive, "with :value" do
148
+ let(:obj) { ExampleSingle.new(:value => 5) }
149
+ let(:io) { ExampleSingle.io_with_value(56) }
150
+
151
+ it "initial state" do
152
+ obj.value.must_equal 5
153
+ end
154
+
155
+ it "changes during reading" do
156
+ obj.read(io)
157
+ obj.stub :reading?, true do
158
+ obj.must_equal 56
159
+ end
160
+ end
161
+
162
+ it "does not change after reading" do
163
+ obj.read(io)
164
+ obj.must_equal 5
165
+ end
166
+
167
+ it "is unaffected by assigning" do
168
+ obj.assign(17)
169
+ obj.must_equal 5
170
+ end
171
+ end
172
+
173
+ describe BinData::BasePrimitive, "checking read value" do
174
+ let(:io) { ExampleSingle.io_with_value(12) }
175
+
176
+ describe ":check_value is non boolean" do
177
+ it "succeeds when check_value is correct" do
178
+ skip "deprecated"
179
+ data = ExampleSingle.new(:check_value => 12)
180
+ data.read(io)
181
+ data.value.must_equal 12
182
+ end
183
+
184
+ it "fails when check_value is incorrect" do
185
+ skip "deprecated"
186
+ data = ExampleSingle.new(:check_value => lambda { 99 })
187
+ lambda { data.read(io) }.must_raise BinData::ValidityError
188
+ end
189
+ end
190
+
191
+ describe ":check_value is boolean" do
192
+ it "succeeds when check_value is true" do
193
+ skip "deprecated"
194
+ data = ExampleSingle.new(:check_value => lambda { value < 20 })
195
+ data.read(io)
196
+ data.value.must_equal 12
197
+ end
198
+
199
+ it "fails when check_value is false" do
200
+ skip "deprecated"
201
+ data = ExampleSingle.new(:check_value => lambda { value > 20 })
202
+ lambda { data.read(io) }.must_raise BinData::ValidityError
203
+ end
204
+ end
205
+ end
206
+
207
+ describe BinData::BasePrimitive, "asserting value" do
208
+ let(:io) { ExampleSingle.io_with_value(12) }
209
+
210
+ describe ":assert is non boolean" do
211
+ it "succeeds when assert is correct" do
212
+ data = ExampleSingle.new(:assert => 12)
213
+ data.read(io)
214
+ data.value.must_equal 12
215
+ end
216
+
217
+ it "fails when assert is incorrect" do
218
+ data = ExampleSingle.new(:assert => lambda { 99 })
219
+ lambda { data.read(io) }.must_raise BinData::ValidityError
220
+ end
221
+ end
222
+
223
+ describe ":assert is boolean" do
224
+ it "succeeds when assert is true" do
225
+ data = ExampleSingle.new(:assert => lambda { value < 20 })
226
+ data.read(io)
227
+ data.value.must_equal 12
228
+ end
229
+
230
+ it "fails when assert is false" do
231
+ data = ExampleSingle.new(:assert => lambda { value > 20 })
232
+ lambda { data.read(io) }.must_raise BinData::ValidityError
233
+ end
234
+ end
235
+
236
+ describe "assigning with :assert" do
237
+ it "succeeds when assert is correct" do
238
+ data = ExampleSingle.new(:assert => 12)
239
+ data.assign(12)
240
+ data.value.must_equal 12
241
+ end
242
+
243
+ it "fails when assert is incorrect" do
244
+ data = ExampleSingle.new(:assert => 12)
245
+ lambda { data.assign(99) }.must_raise BinData::ValidityError
246
+ end
247
+ end
248
+ end
249
+
250
+ describe BinData::BasePrimitive, ":asserted_value" do
251
+ it "has :value" do
252
+ data = ExampleSingle.new(:asserted_value => lambda { 12 })
253
+ data.value.must_equal 12
254
+ end
255
+
256
+ describe "assigning with :assert" do
257
+ it "succeeds when assert is correct" do
258
+ data = ExampleSingle.new(:asserted_value => lambda { 12 })
259
+ data.assign(12)
260
+ data.value.must_equal 12
261
+ end
262
+
263
+ it "fails when assert is incorrect" do
264
+ data = ExampleSingle.new(:asserted_value => lambda { 12 })
265
+ lambda { data.assign(99) }.must_raise BinData::ValidityError
266
+ end
267
+ end
268
+ end
269
+
270
+ describe BinData::BasePrimitive do
271
+ it "conforms to rule 1 for returning a value" do
272
+ data = ExampleSingle.new(:value => 5)
273
+ data.must_equal 5
274
+ end
275
+
276
+ it "conforms to rule 2 for returning a value" do
277
+ io = ExampleSingle.io_with_value(42)
278
+ data = ExampleSingle.new(:value => 5)
279
+ data.read(io)
280
+
281
+ data.stub :reading?, true do
282
+ data.must_equal 42
283
+ end
284
+ end
285
+
286
+ it "conforms to rule 3 for returning a value" do
287
+ data = ExampleSingle.new(:initial_value => 5)
288
+ assert data.clear?
289
+ data.must_equal 5
290
+ end
291
+
292
+ it "conforms to rule 4 for returning a value" do
293
+ data = ExampleSingle.new(:initial_value => 5)
294
+ data.assign(17)
295
+ refute data.clear?
296
+ data.must_equal 17
297
+ end
298
+
299
+ it "conforms to rule 5 for returning a value" do
300
+ data = ExampleSingle.new
301
+ assert data.clear?
302
+ data.must_equal 0
303
+ end
304
+
305
+ it "conforms to rule 6 for returning a value" do
306
+ data = ExampleSingle.new
307
+ data.assign(8)
308
+ refute data.clear?
309
+ data.must_equal 8
310
+ end
311
+ end
312
+