bindata 1.2.2 → 1.3.1
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.
Potentially problematic release.
This version of bindata might be problematic. Click here for more details.
- data/ChangeLog +12 -0
- data/NEWS +53 -0
- data/Rakefile +2 -1
- data/examples/NBT.txt +149 -0
- data/examples/ip_address.rb +1 -2
- data/examples/list.rb +124 -0
- data/examples/nbt.rb +195 -0
- data/lib/bindata.rb +4 -3
- data/lib/bindata/alignment.rb +86 -0
- data/lib/bindata/array.rb +21 -29
- data/lib/bindata/base.rb +82 -81
- data/lib/bindata/base_primitive.rb +66 -48
- data/lib/bindata/choice.rb +18 -28
- data/lib/bindata/deprecated.rb +17 -0
- data/lib/bindata/dsl.rb +25 -15
- data/lib/bindata/int.rb +2 -2
- data/lib/bindata/io.rb +8 -6
- data/lib/bindata/offset.rb +91 -0
- data/lib/bindata/primitive.rb +22 -11
- data/lib/bindata/record.rb +40 -10
- data/lib/bindata/sanitize.rb +15 -30
- data/lib/bindata/string.rb +16 -17
- data/lib/bindata/stringz.rb +0 -1
- data/lib/bindata/struct.rb +17 -6
- data/lib/bindata/trace.rb +52 -0
- data/lib/bindata/wrapper.rb +28 -6
- data/manual.haml +56 -10
- data/manual.md +318 -113
- data/spec/alignment_spec.rb +61 -0
- data/spec/array_spec.rb +139 -178
- data/spec/base_primitive_spec.rb +86 -111
- data/spec/base_spec.rb +200 -172
- data/spec/bits_spec.rb +45 -53
- data/spec/choice_spec.rb +91 -87
- data/spec/deprecated_spec.rb +36 -14
- data/spec/float_spec.rb +16 -68
- data/spec/int_spec.rb +26 -27
- data/spec/io_spec.rb +105 -105
- data/spec/lazy_spec.rb +50 -50
- data/spec/primitive_spec.rb +36 -36
- data/spec/record_spec.rb +134 -134
- data/spec/registry_spec.rb +34 -38
- data/spec/rest_spec.rb +8 -11
- data/spec/skip_spec.rb +9 -17
- data/spec/spec_common.rb +4 -0
- data/spec/string_spec.rb +92 -115
- data/spec/stringz_spec.rb +41 -74
- data/spec/struct_spec.rb +132 -153
- data/spec/system_spec.rb +115 -60
- data/spec/wrapper_spec.rb +63 -31
- data/tasks/pkg.rake +1 -1
- metadata +15 -7
data/spec/base_primitive_spec.rb
CHANGED
@@ -5,26 +5,24 @@ require File.expand_path(File.join(File.dirname(__FILE__), "example"))
|
|
5
5
|
require 'bindata/base_primitive'
|
6
6
|
require 'bindata/io'
|
7
7
|
|
8
|
-
describe BinData::BasePrimitive, "
|
8
|
+
describe BinData::BasePrimitive, "all subclasses" do
|
9
9
|
class SubClassOfBasePrimitive < BinData::BasePrimitive
|
10
10
|
expose_methods_for_testing
|
11
11
|
end
|
12
12
|
|
13
|
-
|
14
|
-
@obj = SubClassOfBasePrimitive.new
|
15
|
-
end
|
13
|
+
subject { SubClassOfBasePrimitive.new }
|
16
14
|
|
17
15
|
it "should raise errors on unimplemented methods" do
|
18
|
-
lambda {
|
19
|
-
lambda {
|
20
|
-
lambda {
|
16
|
+
lambda { subject.value_to_binary_string(nil) }.should raise_error(NotImplementedError)
|
17
|
+
lambda { subject.read_and_return_value(nil) }.should raise_error(NotImplementedError)
|
18
|
+
lambda { subject.sensible_default }.should raise_error(NotImplementedError)
|
21
19
|
end
|
22
20
|
end
|
23
21
|
|
24
22
|
describe BinData::BasePrimitive do
|
25
23
|
it "should conform to rule 1 for returning a value" do
|
26
24
|
data = ExampleSingle.new(:value => 5)
|
27
|
-
data.
|
25
|
+
data.should == 5
|
28
26
|
end
|
29
27
|
|
30
28
|
it "should conform to rule 2 for returning a value" do
|
@@ -32,224 +30,201 @@ describe BinData::BasePrimitive do
|
|
32
30
|
data = ExampleSingle.new(:value => 5)
|
33
31
|
data.read(io)
|
34
32
|
|
35
|
-
|
36
|
-
data.
|
33
|
+
data.stub(:reading?).and_return(true)
|
34
|
+
data.should == 42
|
37
35
|
end
|
38
36
|
|
39
37
|
it "should conform to rule 3 for returning a value" do
|
40
38
|
data = ExampleSingle.new(:initial_value => 5)
|
41
39
|
data.should be_clear
|
42
|
-
data.
|
40
|
+
data.should == 5
|
43
41
|
end
|
44
42
|
|
45
43
|
it "should conform to rule 4 for returning a value" do
|
46
44
|
data = ExampleSingle.new(:initial_value => 5)
|
47
|
-
data.
|
45
|
+
data.assign(17)
|
48
46
|
data.should_not be_clear
|
49
|
-
data.
|
47
|
+
data.should == 17
|
50
48
|
end
|
51
49
|
|
52
50
|
it "should conform to rule 5 for returning a value" do
|
53
51
|
data = ExampleSingle.new
|
54
52
|
data.should be_clear
|
55
|
-
data.
|
53
|
+
data.should == 0
|
56
54
|
end
|
57
55
|
|
58
56
|
it "should conform to rule 6 for returning a value" do
|
59
57
|
data = ExampleSingle.new
|
60
|
-
data.
|
58
|
+
data.assign(8)
|
61
59
|
data.should_not be_clear
|
62
|
-
data.
|
60
|
+
data.should == 8
|
63
61
|
end
|
64
62
|
end
|
65
63
|
|
66
64
|
describe ExampleSingle do
|
67
|
-
|
68
|
-
@data = ExampleSingle.new
|
69
|
-
@data.value = 5
|
70
|
-
end
|
65
|
+
subject { ExampleSingle.new(5) }
|
71
66
|
|
72
67
|
it "should fail when assigning nil values" do
|
73
|
-
lambda {
|
68
|
+
lambda { subject.assign(nil) }.should raise_error(ArgumentError)
|
74
69
|
end
|
75
70
|
|
76
71
|
it "should allowing setting and retrieving value" do
|
77
|
-
|
78
|
-
|
72
|
+
subject.assign(7)
|
73
|
+
subject.should == 7
|
79
74
|
end
|
80
75
|
|
81
76
|
it "should allowing setting and retrieving BinData::BasePrimitives" do
|
82
|
-
|
83
|
-
|
84
|
-
@data.value = obj
|
85
|
-
@data.value.should == 7
|
77
|
+
subject.assign(ExampleSingle.new(7))
|
78
|
+
subject.should == 7
|
86
79
|
end
|
87
80
|
|
88
81
|
it "should respond to known methods" do
|
89
|
-
|
82
|
+
subject.should respond_to(:num_bytes)
|
90
83
|
end
|
91
84
|
|
92
85
|
it "should respond to known methods in #snapshot" do
|
93
|
-
|
86
|
+
subject.should respond_to(:div)
|
94
87
|
end
|
95
88
|
|
96
89
|
it "should not respond to unknown methods in self or #snapshot" do
|
97
|
-
|
90
|
+
subject.should_not respond_to(:does_not_exist)
|
98
91
|
end
|
99
92
|
|
100
93
|
it "should behave as #snapshot" do
|
101
|
-
(
|
102
|
-
(1 +
|
94
|
+
(subject + 1).should == 6
|
95
|
+
(1 + subject).should == 6
|
103
96
|
end
|
104
97
|
|
105
98
|
it "should be equal to other ExampleSingle" do
|
106
|
-
|
107
|
-
other.value = 5
|
108
|
-
@data.should == other
|
99
|
+
subject.should == ExampleSingle.new(5)
|
109
100
|
end
|
110
101
|
|
111
102
|
it "should be equal to raw values" do
|
112
|
-
|
113
|
-
5.should ==
|
103
|
+
subject.should == 5
|
104
|
+
5.should == subject
|
114
105
|
end
|
115
106
|
|
116
107
|
it "should work as hash keys" do
|
117
108
|
hash = {5 => 17}
|
118
109
|
|
119
|
-
|
120
|
-
|
110
|
+
hash[subject].should == 17
|
111
|
+
end
|
121
112
|
|
122
|
-
|
113
|
+
it "should be able to sort" do
|
114
|
+
[ExampleSingle.new(5), ExampleSingle.new(3)].sort.should == [3, 5]
|
123
115
|
end
|
124
116
|
end
|
125
117
|
|
126
118
|
describe BinData::BasePrimitive, "after initialisation" do
|
127
|
-
|
128
|
-
@data = ExampleSingle.new
|
129
|
-
end
|
119
|
+
subject { ExampleSingle.new }
|
130
120
|
|
131
121
|
it "should not allow both :initial_value and :value" do
|
132
122
|
params = {:initial_value => 1, :value => 2}
|
133
123
|
lambda { ExampleSingle.new(params) }.should raise_error(ArgumentError)
|
134
124
|
end
|
135
125
|
|
136
|
-
it
|
137
|
-
|
138
|
-
|
126
|
+
it { should be_clear }
|
127
|
+
its(:value) { should == 0 }
|
128
|
+
its(:num_bytes) { should == 4 }
|
139
129
|
|
140
130
|
it "should have symmetric IO" do
|
141
|
-
|
142
|
-
written =
|
131
|
+
subject.assign(42)
|
132
|
+
written = subject.to_binary_s
|
143
133
|
|
144
134
|
ExampleSingle.read(written).should == 42
|
145
135
|
end
|
146
136
|
|
147
137
|
it "should allowing setting and retrieving value" do
|
148
|
-
|
149
|
-
|
150
|
-
end
|
151
|
-
|
152
|
-
it "should be clear" do
|
153
|
-
@data.should be_clear
|
138
|
+
subject.value = 5
|
139
|
+
subject.value.should == 5
|
154
140
|
end
|
155
141
|
|
156
142
|
it "should not be clear after setting value" do
|
157
|
-
|
158
|
-
|
143
|
+
subject.assign(5)
|
144
|
+
subject.should_not be_clear
|
159
145
|
end
|
160
146
|
|
161
147
|
it "should not be clear after reading" do
|
162
|
-
|
163
|
-
|
164
|
-
end
|
165
|
-
|
166
|
-
it "should return num_bytes" do
|
167
|
-
@data.num_bytes.should == 4
|
148
|
+
subject.read("\x11\x22\x33\x44")
|
149
|
+
subject.should_not be_clear
|
168
150
|
end
|
169
151
|
|
170
152
|
it "should return a snapshot" do
|
171
|
-
|
172
|
-
|
153
|
+
subject.assign(5)
|
154
|
+
subject.snapshot.should == 5
|
173
155
|
end
|
174
156
|
end
|
175
157
|
|
176
158
|
describe BinData::BasePrimitive, "with :initial_value" do
|
177
|
-
|
178
|
-
@data = ExampleSingle.new(:initial_value => 5)
|
179
|
-
end
|
159
|
+
subject { ExampleSingle.new(:initial_value => 5) }
|
180
160
|
|
181
|
-
|
182
|
-
@data.value.should == 5
|
183
|
-
end
|
161
|
+
its(:value) { should == 5 }
|
184
162
|
|
185
163
|
it "should forget :initial_value after being set" do
|
186
|
-
|
187
|
-
|
164
|
+
subject.assign(17)
|
165
|
+
subject.should_not == 5
|
188
166
|
end
|
189
167
|
|
190
168
|
it "should forget :initial_value after reading" do
|
191
|
-
|
192
|
-
|
169
|
+
subject.read("\x11\x22\x33\x44")
|
170
|
+
subject.should_not == 5
|
193
171
|
end
|
194
172
|
|
195
173
|
it "should remember :initial_value after being cleared" do
|
196
|
-
|
197
|
-
|
198
|
-
|
174
|
+
subject.assign(17)
|
175
|
+
subject.clear
|
176
|
+
subject.should == 5
|
199
177
|
end
|
200
178
|
end
|
201
179
|
|
202
180
|
describe BinData::BasePrimitive, "with :value" do
|
203
|
-
|
204
|
-
@data = ExampleSingle.new(:value => 5)
|
205
|
-
end
|
181
|
+
subject { ExampleSingle.new(:value => 5) }
|
206
182
|
|
207
|
-
|
208
|
-
@data.value.should == 5
|
209
|
-
end
|
183
|
+
its(:value) { should == 5 }
|
210
184
|
|
211
|
-
|
212
|
-
io = ExampleSingle.io_with_value(56)
|
213
|
-
@data.read(io)
|
185
|
+
let(:io) { ExampleSingle.io_with_value(56) }
|
214
186
|
|
215
|
-
|
216
|
-
|
187
|
+
it "should change during reading" do
|
188
|
+
subject.read(io)
|
189
|
+
subject.stub(:reading?).and_return(true)
|
190
|
+
subject.should == 56
|
217
191
|
end
|
218
192
|
|
219
193
|
it "should not change after reading" do
|
220
|
-
|
221
|
-
|
222
|
-
@data.value.should == 5
|
194
|
+
subject.read(io)
|
195
|
+
subject.should == 5
|
223
196
|
end
|
224
197
|
|
225
198
|
it "should not be able to change the value" do
|
226
|
-
|
227
|
-
|
199
|
+
subject.assign(17)
|
200
|
+
subject.should == 5
|
228
201
|
end
|
229
202
|
end
|
230
203
|
|
231
|
-
describe BinData::BasePrimitive, "
|
232
|
-
|
233
|
-
@io = ExampleSingle.io_with_value(34)
|
234
|
-
end
|
204
|
+
describe BinData::BasePrimitive, "checking read value" do
|
205
|
+
let(:io) { ExampleSingle.io_with_value(12) }
|
235
206
|
|
236
|
-
|
237
|
-
|
238
|
-
|
239
|
-
|
207
|
+
context ":check_value is non boolean" do
|
208
|
+
it "should succeed when check_value and correct" do
|
209
|
+
data = ExampleSingle.new(:check_value => 12)
|
210
|
+
lambda { data.read(io) }.should_not raise_error
|
211
|
+
end
|
240
212
|
|
241
|
-
|
242
|
-
|
243
|
-
|
213
|
+
it "should fail when check_value is incorrect" do
|
214
|
+
data = ExampleSingle.new(:check_value => lambda { 99 })
|
215
|
+
lambda { data.read(io) }.should raise_error(BinData::ValidityError)
|
216
|
+
end
|
244
217
|
end
|
245
218
|
|
246
|
-
|
247
|
-
|
248
|
-
|
249
|
-
|
219
|
+
context ":check_value is boolean" do
|
220
|
+
it "should succeed when check_value is true" do
|
221
|
+
data = ExampleSingle.new(:check_value => lambda { value < 20 })
|
222
|
+
lambda { data.read(io) }.should_not raise_error
|
223
|
+
end
|
250
224
|
|
251
|
-
|
252
|
-
|
253
|
-
|
225
|
+
it "should fail when check_value is false" do
|
226
|
+
data = ExampleSingle.new(:check_value => lambda { value > 20 })
|
227
|
+
lambda { data.read(io) }.should raise_error(BinData::ValidityError)
|
228
|
+
end
|
254
229
|
end
|
255
230
|
end
|
data/spec/base_spec.rb
CHANGED
@@ -7,49 +7,32 @@ class BaseStub < BinData::Base
|
|
7
7
|
# Override to avoid NotImplemented errors
|
8
8
|
def clear; end
|
9
9
|
def clear?; end
|
10
|
-
def assign(x); end
|
11
|
-
def snapshot; end
|
10
|
+
def assign(x); @data = x; end
|
11
|
+
def snapshot; @data; end
|
12
12
|
def do_read(io) end
|
13
13
|
def do_write(io) end
|
14
14
|
def do_num_bytes; end
|
15
15
|
end
|
16
16
|
|
17
|
-
|
18
|
-
attr_accessor :mock
|
19
|
-
def clear; mock.clear; end
|
20
|
-
def clear?; mock.clear?; end
|
21
|
-
def assign(x); mock.assign(x); end
|
22
|
-
def snapshot; mock.snapshot; end
|
23
|
-
def do_read(io) mock.do_read(io); end
|
24
|
-
def do_write(io) mock.do_write(io); end
|
25
|
-
def do_num_bytes; mock.do_num_bytes; end
|
26
|
-
end
|
27
|
-
|
28
|
-
describe BinData::Base, "when subclassing" do
|
17
|
+
describe BinData::Base, "all subclasses" do
|
29
18
|
class SubClassOfBase < BinData::Base
|
30
19
|
expose_methods_for_testing
|
31
20
|
end
|
32
21
|
|
33
|
-
|
34
|
-
@obj = SubClassOfBase.new
|
35
|
-
end
|
22
|
+
subject { SubClassOfBase.new }
|
36
23
|
|
37
24
|
it "should raise errors on unimplemented methods" do
|
38
|
-
lambda {
|
39
|
-
lambda {
|
40
|
-
lambda {
|
41
|
-
lambda {
|
42
|
-
lambda {
|
43
|
-
lambda {
|
44
|
-
lambda {
|
25
|
+
lambda { subject.clear }.should raise_error(NotImplementedError)
|
26
|
+
lambda { subject.clear? }.should raise_error(NotImplementedError)
|
27
|
+
lambda { subject.assign(nil) }.should raise_error(NotImplementedError)
|
28
|
+
lambda { subject.snapshot }.should raise_error(NotImplementedError)
|
29
|
+
lambda { subject.do_read(nil) }.should raise_error(NotImplementedError)
|
30
|
+
lambda { subject.do_write(nil) }.should raise_error(NotImplementedError)
|
31
|
+
lambda { subject.do_num_bytes }.should raise_error(NotImplementedError)
|
45
32
|
end
|
46
33
|
end
|
47
34
|
|
48
35
|
describe BinData::Base, "with parameters" do
|
49
|
-
it "should raise error if parameter has nil value" do
|
50
|
-
lambda { BaseStub.new(:a => nil) }.should raise_error(ArgumentError)
|
51
|
-
end
|
52
|
-
|
53
36
|
it "should raise error if parameter name is invalid" do
|
54
37
|
lambda {
|
55
38
|
class InvalidParameterNameBase < BinData::Base
|
@@ -58,10 +41,13 @@ describe BinData::Base, "with parameters" do
|
|
58
41
|
}.should raise_error(NameError)
|
59
42
|
end
|
60
43
|
|
61
|
-
it "should
|
62
|
-
|
63
|
-
|
64
|
-
|
44
|
+
it "should raise error if parameter has nil value" do
|
45
|
+
lambda { BaseStub.new(:a => nil) }.should raise_error(ArgumentError)
|
46
|
+
end
|
47
|
+
|
48
|
+
it "should convert parameter keys to symbols" do
|
49
|
+
subject = BaseStub.new('a' => 3)
|
50
|
+
subject.should have_parameter(:a)
|
65
51
|
end
|
66
52
|
end
|
67
53
|
|
@@ -92,15 +78,13 @@ describe BinData::Base, "with default parameters" do
|
|
92
78
|
end
|
93
79
|
|
94
80
|
it "should use default parameters when not specified" do
|
95
|
-
|
96
|
-
|
97
|
-
obj.eval_parameter(:p1).should == "a"
|
81
|
+
subject = DefaultBase.new
|
82
|
+
subject.eval_parameter(:p1).should == "a"
|
98
83
|
end
|
99
84
|
|
100
85
|
it "should be able to override default parameters" do
|
101
|
-
|
102
|
-
|
103
|
-
obj.eval_parameter(:p1).should == "b"
|
86
|
+
subject = DefaultBase.new(:p1 => "b")
|
87
|
+
subject.eval_parameter(:p1).should == "b"
|
104
88
|
end
|
105
89
|
end
|
106
90
|
|
@@ -127,8 +111,8 @@ end
|
|
127
111
|
describe BinData::Base, "with multiple parameters" do
|
128
112
|
class WithParamBase < BaseStub
|
129
113
|
mandatory_parameter :p1
|
130
|
-
|
131
|
-
|
114
|
+
default_parameter :p2 => 2
|
115
|
+
optional_parameter :p3
|
132
116
|
end
|
133
117
|
|
134
118
|
it "should identify internally accepted parameters" do
|
@@ -139,124 +123,110 @@ describe BinData::Base, "with multiple parameters" do
|
|
139
123
|
accepted.should_not include(:xx)
|
140
124
|
end
|
141
125
|
|
142
|
-
|
143
|
-
|
144
|
-
|
145
|
-
|
146
|
-
|
126
|
+
context "examining parameters" do
|
127
|
+
subject {
|
128
|
+
params = {:p1 => 1, :p3 => :xx, :p4 => lambda { 4 }}
|
129
|
+
WithParamBase.new(params)
|
130
|
+
}
|
147
131
|
|
148
|
-
|
149
|
-
|
150
|
-
|
151
|
-
|
152
|
-
|
153
|
-
|
154
|
-
it "should have parameters" do
|
155
|
-
params = {:p1 => 1, :p2 => 2, :p3 => 3, :p4 => 4}
|
156
|
-
obj = WithParamBase.new(params)
|
157
|
-
obj.should have_parameter(:p4)
|
158
|
-
end
|
132
|
+
it "should evaluate parameters" do
|
133
|
+
subject.eval_parameter(:p1).should == 1
|
134
|
+
subject.eval_parameter(:p2).should == 2
|
135
|
+
lambda { subject.eval_parameter(:p3) }.should raise_error(NoMethodError)
|
136
|
+
subject.eval_parameter(:p4).should == 4
|
137
|
+
end
|
159
138
|
|
160
|
-
|
161
|
-
|
162
|
-
|
139
|
+
it "should get parameters without evaluating" do
|
140
|
+
subject.get_parameter(:p1).should == 1
|
141
|
+
subject.get_parameter(:p2).should == 2
|
142
|
+
subject.get_parameter(:p3).should == :xx
|
143
|
+
subject.get_parameter(:p4).should respond_to(:arity)
|
144
|
+
end
|
163
145
|
|
164
|
-
|
165
|
-
|
166
|
-
|
167
|
-
|
168
|
-
|
146
|
+
it "should have parameters" do
|
147
|
+
subject.should have_parameter(:p1)
|
148
|
+
subject.should have_parameter(:p2)
|
149
|
+
subject.should have_parameter(:p3)
|
150
|
+
subject.should have_parameter(:p4)
|
151
|
+
end
|
169
152
|
end
|
170
153
|
end
|
171
154
|
|
172
|
-
describe BinData::Base, "
|
173
|
-
class
|
174
|
-
|
175
|
-
|
176
|
-
|
155
|
+
describe BinData::Base, "when initializing" do
|
156
|
+
class BaseInit < BaseStub
|
157
|
+
class << self
|
158
|
+
attr_accessor :calls
|
159
|
+
def recorded_calls(&block)
|
160
|
+
self.calls = []
|
161
|
+
block.call
|
162
|
+
calls
|
163
|
+
end
|
177
164
|
end
|
178
165
|
|
179
|
-
def
|
180
|
-
|
181
|
-
@child.do_read(io)
|
166
|
+
def initialize_instance
|
167
|
+
self.class.calls << :initialize_instance
|
182
168
|
end
|
183
|
-
end
|
184
|
-
|
185
|
-
before(:each) do
|
186
|
-
@io = StringIO.new("12345678901234567890")
|
187
|
-
end
|
188
|
-
|
189
|
-
it "should fail if offset is incorrect" do
|
190
|
-
@io.seek(2)
|
191
|
-
obj = TenByteOffsetBase.new(:check_offset => 8)
|
192
|
-
lambda { obj.read(@io) }.should raise_error(BinData::ValidityError)
|
193
|
-
end
|
194
169
|
|
195
|
-
|
196
|
-
|
197
|
-
|
198
|
-
lambda { obj.read(@io) }.should_not raise_error
|
170
|
+
def initialize_shared_instance
|
171
|
+
self.class.calls << :initialize_shared_instance
|
172
|
+
end
|
199
173
|
end
|
200
174
|
|
201
|
-
it "should
|
202
|
-
|
203
|
-
|
204
|
-
|
175
|
+
it "should call both #initialize_xxx methods when initializing" do
|
176
|
+
BaseInit.recorded_calls {
|
177
|
+
BaseInit.new
|
178
|
+
}.should == [:initialize_shared_instance, :initialize_instance]
|
205
179
|
end
|
206
180
|
|
207
|
-
|
208
|
-
|
209
|
-
obj = TenByteOffsetBase.new(:check_offset => lambda { offset == 10 } )
|
210
|
-
lambda { obj.read(@io) }.should_not raise_error
|
211
|
-
end
|
212
|
-
end
|
181
|
+
context "as a factory" do
|
182
|
+
subject { BaseInit.new(:check_offset => 1) }
|
213
183
|
|
214
|
-
describe
|
215
|
-
|
216
|
-
|
217
|
-
super({})
|
218
|
-
@child = BaseStub.new(params, self)
|
219
|
-
end
|
184
|
+
describe "#new" do
|
185
|
+
it "should call #initialize_instance" do
|
186
|
+
obj = subject
|
220
187
|
|
221
|
-
|
222
|
-
|
223
|
-
|
224
|
-
|
225
|
-
end
|
188
|
+
BaseInit.recorded_calls {
|
189
|
+
obj.new
|
190
|
+
}.should == [:initialize_instance]
|
191
|
+
end
|
226
192
|
|
227
|
-
|
228
|
-
|
229
|
-
|
193
|
+
it "should copy parameters" do
|
194
|
+
obj = subject.new
|
195
|
+
obj.eval_parameter(:check_offset).should == 1
|
196
|
+
end
|
230
197
|
|
231
|
-
|
232
|
-
|
233
|
-
|
234
|
-
|
198
|
+
it "should perform action for :check_offset" do
|
199
|
+
obj = subject.new
|
200
|
+
lambda {
|
201
|
+
obj.read("abc")
|
202
|
+
}.should raise_error(BinData::ValidityError)
|
203
|
+
end
|
235
204
|
|
236
|
-
|
237
|
-
|
238
|
-
|
239
|
-
|
240
|
-
@io.pos.should == (2 + 13)
|
241
|
-
end
|
205
|
+
it "should assign value" do
|
206
|
+
obj = subject.new(3)
|
207
|
+
obj.snapshot.should == 3
|
208
|
+
end
|
242
209
|
|
243
|
-
|
244
|
-
|
245
|
-
|
246
|
-
|
247
|
-
|
210
|
+
it "should set parent" do
|
211
|
+
obj = subject.new(3, "p")
|
212
|
+
obj.parent.should == "p"
|
213
|
+
end
|
214
|
+
end
|
248
215
|
end
|
216
|
+
end
|
249
217
|
|
250
|
-
|
251
|
-
@io.seek(3)
|
252
|
-
obj = TenByteAdjustingOffsetBase.new(:adjust_offset => -4)
|
253
|
-
lambda { obj.read(@io) }.should raise_error(BinData::ValidityError)
|
254
|
-
end
|
218
|
+
describe BinData::Base, "as a factory" do
|
255
219
|
end
|
256
220
|
|
257
221
|
describe BinData::Base, "as black box" do
|
258
|
-
|
259
|
-
|
222
|
+
context "class methods" do
|
223
|
+
it "should return bindata_name" do
|
224
|
+
BaseStub.bindata_name.should == "base_stub"
|
225
|
+
end
|
226
|
+
|
227
|
+
it "should instantiate self for ::read" do
|
228
|
+
BaseStub.read("").class.should == BaseStub
|
229
|
+
end
|
260
230
|
end
|
261
231
|
|
262
232
|
it "should access parent" do
|
@@ -265,47 +235,34 @@ describe BinData::Base, "as black box" do
|
|
265
235
|
child.parent.should == parent
|
266
236
|
end
|
267
237
|
|
268
|
-
|
269
|
-
BaseStub.read("").class.should == BaseStub
|
270
|
-
end
|
238
|
+
subject { BaseStub.new }
|
271
239
|
|
272
240
|
it "should return self for #read" do
|
273
|
-
|
274
|
-
obj.read("").should == obj
|
241
|
+
subject.read("").should == subject
|
275
242
|
end
|
276
243
|
|
277
244
|
it "should return self for #write" do
|
278
|
-
|
279
|
-
obj.write("").should == obj
|
245
|
+
subject.write("").should == subject
|
280
246
|
end
|
281
247
|
|
282
248
|
it "should forward #inspect to snapshot" do
|
283
|
-
|
284
|
-
|
285
|
-
end
|
286
|
-
obj = SnapshotBase.new
|
287
|
-
obj.inspect.should == obj.snapshot.inspect
|
249
|
+
subject.stub(:snapshot).and_return([1, 2, 3])
|
250
|
+
subject.inspect.should == subject.snapshot.inspect
|
288
251
|
end
|
289
252
|
|
290
253
|
it "should forward #to_s to snapshot" do
|
291
|
-
|
292
|
-
|
293
|
-
end
|
294
|
-
obj = SnapshotBase.new
|
295
|
-
obj.to_s.should == obj.snapshot.to_s
|
254
|
+
subject.stub(:snapshot).and_return([1, 2, 3])
|
255
|
+
subject.to_s.should == subject.snapshot.to_s
|
296
256
|
end
|
297
257
|
|
298
258
|
it "should pretty print object as snapshot" do
|
299
|
-
|
300
|
-
def snapshot; [1, 2, 3]; end
|
301
|
-
end
|
302
|
-
obj = SnapshotBase.new
|
259
|
+
subject.stub(:snapshot).and_return([1, 2, 3])
|
303
260
|
actual_io = StringIO.new
|
304
261
|
expected_io = StringIO.new
|
305
262
|
|
306
263
|
require 'pp'
|
307
|
-
PP.pp(
|
308
|
-
PP.pp(
|
264
|
+
PP.pp(subject, actual_io)
|
265
|
+
PP.pp(subject.snapshot, expected_io)
|
309
266
|
|
310
267
|
actual_io.value.should == expected_io.value
|
311
268
|
end
|
@@ -315,37 +272,108 @@ describe BinData::Base, "as black box" do
|
|
315
272
|
def do_write(io) io.writebytes("abc"); end
|
316
273
|
end
|
317
274
|
|
318
|
-
|
275
|
+
subject = WriteToSBase.new
|
319
276
|
io = StringIO.new
|
320
|
-
|
321
|
-
io.value.should ==
|
277
|
+
subject.write(io)
|
278
|
+
io.value.should == subject.to_binary_s
|
322
279
|
end
|
323
280
|
end
|
324
281
|
|
325
282
|
describe BinData::Base, "as white box" do
|
326
|
-
|
327
|
-
@obj = MockBaseStub.new
|
328
|
-
@obj.mock = mock('mock')
|
329
|
-
end
|
283
|
+
subject { BaseStub.new }
|
330
284
|
|
331
285
|
it "should forward read to do_read" do
|
332
|
-
|
333
|
-
|
334
|
-
|
286
|
+
subject.should_receive(:clear).ordered
|
287
|
+
subject.should_receive(:do_read).ordered
|
288
|
+
subject.read(nil)
|
335
289
|
end
|
336
290
|
|
337
291
|
it "should forward write to do_write" do
|
338
|
-
|
339
|
-
|
292
|
+
subject.should_receive(:do_write)
|
293
|
+
subject.write(nil)
|
340
294
|
end
|
341
295
|
|
342
296
|
it "should forward num_bytes to do_num_bytes" do
|
343
|
-
|
344
|
-
|
297
|
+
subject.should_receive(:do_num_bytes).and_return(42)
|
298
|
+
subject.num_bytes.should == 42
|
345
299
|
end
|
346
300
|
|
347
301
|
it "should round up fractional num_bytes" do
|
348
|
-
|
349
|
-
|
302
|
+
subject.should_receive(:do_num_bytes).and_return(42.1)
|
303
|
+
subject.num_bytes.should == 43
|
304
|
+
end
|
305
|
+
end
|
306
|
+
|
307
|
+
describe BinData::Base, "checking offsets" do
|
308
|
+
class TenByteOffsetBase < BaseStub
|
309
|
+
def self.create(params)
|
310
|
+
obj = self.new
|
311
|
+
obj.initialize_child(params)
|
312
|
+
obj
|
313
|
+
end
|
314
|
+
|
315
|
+
def initialize_child(params)
|
316
|
+
@child = BaseStub.new(params, self)
|
317
|
+
end
|
318
|
+
|
319
|
+
def do_read(io)
|
320
|
+
io.seekbytes(10)
|
321
|
+
@child.do_read(io)
|
322
|
+
end
|
323
|
+
end
|
324
|
+
|
325
|
+
let(:io) { StringIO.new("12345678901234567890") }
|
326
|
+
|
327
|
+
context "with :check_offset" do
|
328
|
+
it "should fail if offset is incorrect" do
|
329
|
+
io.seek(2)
|
330
|
+
subject = TenByteOffsetBase.create(:check_offset => 8)
|
331
|
+
lambda { subject.read(io) }.should raise_error(BinData::ValidityError)
|
332
|
+
end
|
333
|
+
|
334
|
+
it "should succeed if offset is correct" do
|
335
|
+
io.seek(3)
|
336
|
+
subject = TenByteOffsetBase.create(:check_offset => 10)
|
337
|
+
lambda { subject.read(io) }.should_not raise_error
|
338
|
+
end
|
339
|
+
|
340
|
+
it "should fail if :check_offset fails" do
|
341
|
+
io.seek(4)
|
342
|
+
subject = TenByteOffsetBase.create(:check_offset => lambda { offset == 11 } )
|
343
|
+
lambda { subject.read(io) }.should raise_error(BinData::ValidityError)
|
344
|
+
end
|
345
|
+
|
346
|
+
it "should succeed if :check_offset succeeds" do
|
347
|
+
io.seek(5)
|
348
|
+
subject = TenByteOffsetBase.create(:check_offset => lambda { offset == 10 } )
|
349
|
+
lambda { subject.read(io) }.should_not raise_error
|
350
|
+
end
|
351
|
+
end
|
352
|
+
|
353
|
+
context "with :adjust_offset" do
|
354
|
+
it "should be mutually exclusive with :check_offset" do
|
355
|
+
params = { :check_offset => 8, :adjust_offset => 8 }
|
356
|
+
lambda { TenByteOffsetBase.create(params) }.should raise_error(ArgumentError)
|
357
|
+
end
|
358
|
+
|
359
|
+
it "should adjust if offset is incorrect" do
|
360
|
+
io.seek(2)
|
361
|
+
subject = TenByteOffsetBase.create(:adjust_offset => 13)
|
362
|
+
subject.read(io)
|
363
|
+
io.pos.should == (2 + 13)
|
364
|
+
end
|
365
|
+
|
366
|
+
it "should succeed if offset is correct" do
|
367
|
+
io.seek(3)
|
368
|
+
subject = TenByteOffsetBase.create(:adjust_offset => 10)
|
369
|
+
lambda { subject.read(io) }.should_not raise_error
|
370
|
+
io.pos.should == (3 + 10)
|
371
|
+
end
|
372
|
+
|
373
|
+
it "should fail if cannot adjust offset" do
|
374
|
+
io.seek(4)
|
375
|
+
subject = TenByteOffsetBase.create(:adjust_offset => -5)
|
376
|
+
lambda { subject.read(io) }.should raise_error(BinData::ValidityError)
|
377
|
+
end
|
350
378
|
end
|
351
379
|
end
|