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.
- data/ChangeLog.rdoc +7 -0
- data/NEWS.rdoc +11 -0
- data/Rakefile +6 -1
- data/bindata.gemspec +2 -1
- data/doc/manual.md +17 -9
- data/examples/gzip.rb +2 -2
- data/examples/list.rb +2 -2
- data/lib/bindata/alignment.rb +4 -9
- data/lib/bindata/array.rb +57 -51
- data/lib/bindata/base.rb +13 -110
- data/lib/bindata/base_primitive.rb +130 -75
- data/lib/bindata/bits.rb +5 -7
- data/lib/bindata/choice.rb +24 -32
- data/lib/bindata/dsl.rb +1 -6
- data/lib/bindata/framework.rb +81 -0
- data/lib/bindata/int.rb +5 -7
- data/lib/bindata/name.rb +28 -0
- data/lib/bindata/offset.rb +42 -53
- data/lib/bindata/params.rb +33 -38
- data/lib/bindata/struct.rb +2 -6
- data/lib/bindata/trace.rb +16 -16
- data/lib/bindata/version.rb +1 -1
- data/lib/bindata/virtual.rb +3 -3
- data/{spec/alignment_spec.rb → test/alignment_test.rb} +17 -16
- data/test/array_test.rb +371 -0
- data/test/base_primitive_test.rb +312 -0
- data/test/base_test.rb +183 -0
- data/{spec/bits_spec.rb → test/bits_test.rb} +59 -59
- data/test/choice_test.rb +260 -0
- data/{spec/spec_common.rb → test/common.rb} +33 -18
- data/test/count_bytes_remaining_test.rb +41 -0
- data/{spec/deprecated_spec.rb → test/deprecated_test.rb} +5 -7
- data/test/float_test.rb +72 -0
- data/{spec/int_spec.rb → test/int_test.rb} +34 -43
- data/{spec/io_spec.rb → test/io_test.rb} +70 -71
- data/{spec/lazy_spec.rb → test/lazy_test.rb} +38 -39
- data/test/offset_test.rb +93 -0
- data/test/params_test.rb +144 -0
- data/{spec/primitive_spec.rb → test/primitive_test.rb} +42 -54
- data/{spec/record_spec.rb → test/record_test.rb} +133 -154
- data/test/registry_test.rb +104 -0
- data/test/rest_test.rb +29 -0
- data/test/skip_test.rb +28 -0
- data/{spec/string_spec.rb → test/string_test.rb} +96 -97
- data/test/stringz_test.rb +127 -0
- data/{spec/struct_spec.rb → test/struct_test.rb} +119 -120
- data/{spec/system_spec.rb → test/system_test.rb} +66 -106
- metadata +39 -38
- data/lib/a.rb +0 -24
- data/spec/array_spec.rb +0 -331
- data/spec/base_primitive_spec.rb +0 -238
- data/spec/base_spec.rb +0 -376
- data/spec/choice_spec.rb +0 -263
- data/spec/count_bytes_remaining_spec.rb +0 -38
- data/spec/example.rb +0 -21
- data/spec/float_spec.rb +0 -37
- data/spec/registry_spec.rb +0 -108
- data/spec/rest_spec.rb +0 -26
- data/spec/skip_spec.rb +0 -27
- data/spec/stringz_spec.rb +0 -118
- data/tasks/rspec.rake +0 -17
data/test/array_test.rb
ADDED
@@ -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
|
+
|