julik-depix 1.0.2
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.
- data/DPX_HEADER_STRUCTURE.txt +97 -0
- data/History.txt +18 -0
- data/Manifest.txt +17 -0
- data/README.txt +59 -0
- data/Rakefile +19 -0
- data/bin/depix-describe +23 -0
- data/lib/depix/compact_structs.rb +42 -0
- data/lib/depix/dict.rb +357 -0
- data/lib/depix/enums.rb +43 -0
- data/lib/depix/struct_explainer.rb +59 -0
- data/lib/depix/structs.rb +137 -0
- data/lib/depix.rb +142 -0
- data/test/samples/E012_P001_L000002_lin.0001.dpx +0 -0
- data/test/samples/E012_P001_L000002_lin.0002.dpx +0 -0
- data/test/samples/E012_P001_L000002_log.0001.dpx +0 -0
- data/test/samples/E012_P001_L000002_log.0002.dpx +0 -0
- data/test/test_depix.rb +98 -0
- data/test/test_dict.rb +686 -0
- metadata +84 -0
data/test/test_dict.rb
ADDED
@@ -0,0 +1,686 @@
|
|
1
|
+
require File.dirname(__FILE__) + '/../lib/depix/dict'
|
2
|
+
require 'test/unit'
|
3
|
+
|
4
|
+
include Depix
|
5
|
+
|
6
|
+
module FieldConformity
|
7
|
+
def conform_field!(f)
|
8
|
+
assert_respond_to f, :name
|
9
|
+
assert_respond_to f, :length
|
10
|
+
assert_respond_to f, :pattern
|
11
|
+
assert_respond_to f, :req
|
12
|
+
assert_respond_to f, :req?
|
13
|
+
assert_respond_to f, :rtype
|
14
|
+
assert_respond_to f, :explain
|
15
|
+
end
|
16
|
+
|
17
|
+
def assert_method_removed(f, method)
|
18
|
+
fail("#{f.inspect} should not respond to #{method}") if f.respond_to?(method)
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
class FieldExplainsItself < Test::Unit::TestCase
|
23
|
+
def test_explain
|
24
|
+
f = Field.new :rtype => self.class, :desc => "Eats people"
|
25
|
+
assert_equal "(FieldExplainsItself) Eats people", f.explain
|
26
|
+
end
|
27
|
+
|
28
|
+
def test_explain_with_verbatim
|
29
|
+
f = Field.new :desc => "Eats people"
|
30
|
+
assert_equal "Eats people", f.explain
|
31
|
+
end
|
32
|
+
|
33
|
+
def test_explain_with_verbatim_and_required
|
34
|
+
f = Field.new :desc => "Eats people", :req => true
|
35
|
+
assert_equal "Eats people - required", f.explain
|
36
|
+
end
|
37
|
+
|
38
|
+
def test_explain_with_no_data
|
39
|
+
f = Field.new
|
40
|
+
assert_equal "", f.explain
|
41
|
+
end
|
42
|
+
|
43
|
+
def test_explaion_for_empty_array
|
44
|
+
f = ArrayField.new
|
45
|
+
assert_equal "Empty array", f.explain
|
46
|
+
end
|
47
|
+
|
48
|
+
def test_explain_for_array_with_members
|
49
|
+
f = ArrayField.new :members => [U8Field.new, U8Field.new], :desc => "Eats babies"
|
50
|
+
assert_equal "(Array of 2 Integer fields) Eats babies", f.explain
|
51
|
+
end
|
52
|
+
|
53
|
+
def test_explain_for_nested_struct
|
54
|
+
f = InnerField.new :cast => self.class, :desc => "Link to test case"
|
55
|
+
assert_equal "(FieldExplainsItself) Link to test case", f.explain
|
56
|
+
end
|
57
|
+
|
58
|
+
end
|
59
|
+
|
60
|
+
class TestField < Test::Unit::TestCase
|
61
|
+
include FieldConformity
|
62
|
+
|
63
|
+
def test_field_responds_to_all_meths
|
64
|
+
f = Field.new
|
65
|
+
conform_field!(f)
|
66
|
+
|
67
|
+
assert_respond_to f, :name=
|
68
|
+
assert_respond_to f, :length=
|
69
|
+
assert_respond_to f, :pattern=
|
70
|
+
assert_respond_to f, :req=
|
71
|
+
end
|
72
|
+
|
73
|
+
def test_field_supports_hash_initialization
|
74
|
+
f = Field.new :name => "foo", :length => 3, :pattern => "C3"
|
75
|
+
assert_equal ["foo", 3, "C3"], [f.name, f.length, f.pattern]
|
76
|
+
end
|
77
|
+
|
78
|
+
def test_req?
|
79
|
+
f = Field.new :name => "foo"
|
80
|
+
assert !f.req?
|
81
|
+
|
82
|
+
f = Field.new :name => "foo", :req => false
|
83
|
+
assert !f.req?
|
84
|
+
|
85
|
+
f = Field.new :name => "foo", :req => true
|
86
|
+
assert f.req?
|
87
|
+
end
|
88
|
+
|
89
|
+
def test_consume_for_field
|
90
|
+
f = Field.new :name => "foo"
|
91
|
+
|
92
|
+
assert_respond_to f, :consume!
|
93
|
+
assert_nil f.consume!([])
|
94
|
+
assert_equal 1, f.consume!([1])
|
95
|
+
assert_equal 2, f.consume!([2,"foo"])
|
96
|
+
|
97
|
+
ar = [1,2,3]
|
98
|
+
f.consume!(ar)
|
99
|
+
assert_equal [2,3], ar
|
100
|
+
end
|
101
|
+
|
102
|
+
def test_consume_for_inner_field
|
103
|
+
catcher = Class.new do
|
104
|
+
def self.consume!(arg)
|
105
|
+
raise RuntimeError if arg == ["julik"]
|
106
|
+
end
|
107
|
+
end
|
108
|
+
|
109
|
+
f = InnerField.new :cast => catcher
|
110
|
+
assert_respond_to f, :consume!
|
111
|
+
|
112
|
+
assert_raise(RuntimeError) { f.consume!(["julik"]) }
|
113
|
+
end
|
114
|
+
|
115
|
+
def test_consume_for_array
|
116
|
+
f = ArrayField.new :members => [Field.new, Field.new]
|
117
|
+
assert_respond_to f, :consume!
|
118
|
+
|
119
|
+
assert_equal [1,2], f.consume!([1,2])
|
120
|
+
end
|
121
|
+
end
|
122
|
+
|
123
|
+
class TestArrayField < Test::Unit::TestCase
|
124
|
+
include FieldConformity
|
125
|
+
|
126
|
+
def test_array_field_conform_field!s_to_field_and_has_extra_methods
|
127
|
+
f = ArrayField.new
|
128
|
+
conform_field!(f)
|
129
|
+
|
130
|
+
assert_respond_to f, :name=
|
131
|
+
|
132
|
+
assert_method_removed f, :length=
|
133
|
+
assert_method_removed f, :pattern=
|
134
|
+
end
|
135
|
+
|
136
|
+
def test_array_does_not_allow_setting_length
|
137
|
+
f = ArrayField.new
|
138
|
+
assert_method_removed(f, :length=)
|
139
|
+
assert_method_removed(f, :pattern=)
|
140
|
+
end
|
141
|
+
|
142
|
+
def test_array_field_has_members
|
143
|
+
f = ArrayField.new
|
144
|
+
assert_respond_to f, :members
|
145
|
+
assert_respond_to f, :members=
|
146
|
+
end
|
147
|
+
|
148
|
+
def test_rtype_for_array_field_is_array
|
149
|
+
casted = ArrayField.new(:members => [])
|
150
|
+
assert_equal Array, casted.rtype
|
151
|
+
end
|
152
|
+
|
153
|
+
def test_array_field_accumulates_lengths_and_patterns_from_members
|
154
|
+
f = ArrayField.new(:members => [
|
155
|
+
Field.new(:name => :foo, :length => 1, :pattern => "C"),
|
156
|
+
Field.new(:name => :bar, :length => 2, :pattern => "C2"),
|
157
|
+
])
|
158
|
+
|
159
|
+
assert_equal 3, f.length
|
160
|
+
assert_equal "CC2", f.pattern
|
161
|
+
end
|
162
|
+
end
|
163
|
+
|
164
|
+
class TestInnerField < Test::Unit::TestCase
|
165
|
+
|
166
|
+
include FieldConformity
|
167
|
+
|
168
|
+
def test_inner_field_conforms_to_field_and_has_extra_methods
|
169
|
+
f = InnerField.new
|
170
|
+
conform_field!(f)
|
171
|
+
|
172
|
+
assert_respond_to f, :cast
|
173
|
+
assert_respond_to f, :cast=
|
174
|
+
|
175
|
+
assert_method_removed(f, :length=)
|
176
|
+
assert_method_removed(f, :pattern=)
|
177
|
+
end
|
178
|
+
|
179
|
+
def test_inner_field_asks_cast_for_pattern_and_length
|
180
|
+
sample = Struct.new(:length, :pattern).new
|
181
|
+
sample.length, sample.pattern = 123, "C123"
|
182
|
+
|
183
|
+
casted = InnerField.new(:cast => sample)
|
184
|
+
assert_equal 123, casted.length
|
185
|
+
assert_equal 'C123', casted.pattern
|
186
|
+
|
187
|
+
assert_method_removed(casted, :length=)
|
188
|
+
assert_method_removed(casted, :pattern=)
|
189
|
+
|
190
|
+
end
|
191
|
+
|
192
|
+
def test_rtype_for_inner_field_is_cast
|
193
|
+
c = Class.new
|
194
|
+
casted = InnerField.new(:cast => c)
|
195
|
+
assert_equal c, casted.rtype
|
196
|
+
end
|
197
|
+
end
|
198
|
+
|
199
|
+
class TestWideIntField < Test::Unit::TestCase
|
200
|
+
include FieldConformity
|
201
|
+
|
202
|
+
def test_u32_field_contorms_to_basics
|
203
|
+
f = U32Field.new :name => :foo
|
204
|
+
conform_field!(f)
|
205
|
+
|
206
|
+
assert_equal "N", f.pattern
|
207
|
+
assert_equal 4, f.length
|
208
|
+
assert_equal :foo, f.name
|
209
|
+
assert_equal 66, f.clean(66)
|
210
|
+
assert_equal nil, f.clean(0xFFFFFFFF)
|
211
|
+
end
|
212
|
+
end
|
213
|
+
|
214
|
+
class TestCharField < Test::Unit::TestCase
|
215
|
+
include FieldConformity
|
216
|
+
|
217
|
+
def test_char_field_conforms_to_basics
|
218
|
+
f = CharField.new :name => :foo
|
219
|
+
conform_field!(f)
|
220
|
+
assert_method_removed(f, :pattern=)
|
221
|
+
end
|
222
|
+
|
223
|
+
def test_char_field_pads
|
224
|
+
f = CharField.new :name => :foo, :length => 15
|
225
|
+
|
226
|
+
assert_equal "A15", f.pattern
|
227
|
+
assert_equal 15, f.length
|
228
|
+
assert_equal String, f.rtype
|
229
|
+
end
|
230
|
+
|
231
|
+
def test_char_field_does_not_clean_inner_nulls
|
232
|
+
f = CharField.new :name => :foo, :length => 15
|
233
|
+
assert_equal "foo\0foo", f.clean("\0\0foo\0foo\0")
|
234
|
+
assert_equal "swoop\377\0bla", f.clean("\0\0\0\377\377swoop\377\0bla\0\0\0\377\377\377\377\0\0\0")
|
235
|
+
end
|
236
|
+
|
237
|
+
def test_char_field_clean_blank
|
238
|
+
f = CharField.new :name => :foo, :length => 15
|
239
|
+
assert_equal nil, f.clean("\0")
|
240
|
+
assert_equal nil, f.clean("\0\0\0\0\0\0")
|
241
|
+
assert_equal nil, f.clean("\0\0\0\377\377\0\0\0")
|
242
|
+
assert_equal "foo\0foo", f.clean("\0\0foo\0foo\0")
|
243
|
+
|
244
|
+
end
|
245
|
+
end
|
246
|
+
|
247
|
+
class TestFloatField < Test::Unit::TestCase
|
248
|
+
include FieldConformity
|
249
|
+
|
250
|
+
def test_r32_field_contorms_to_basics
|
251
|
+
f = R32Field.new :name => :foo
|
252
|
+
conform_field!(f)
|
253
|
+
|
254
|
+
the_nan = Class.new do
|
255
|
+
def nan?; true; end
|
256
|
+
end.new
|
257
|
+
|
258
|
+
assert_equal "g", f.pattern
|
259
|
+
assert_equal 4, f.length
|
260
|
+
assert_equal :foo, f.name
|
261
|
+
assert_equal Float, f.rtype
|
262
|
+
assert_equal nil, f.clean(the_nan)
|
263
|
+
end
|
264
|
+
end
|
265
|
+
|
266
|
+
class TestSmallintField < Test::Unit::TestCase
|
267
|
+
include FieldConformity
|
268
|
+
|
269
|
+
def test_smallint_conformity
|
270
|
+
f = U8Field.new :name => :foo
|
271
|
+
conform_field!(f)
|
272
|
+
|
273
|
+
assert_method_removed(f, :pattern=)
|
274
|
+
assert_method_removed(f, :length=)
|
275
|
+
|
276
|
+
end
|
277
|
+
|
278
|
+
def test_smallint_operation
|
279
|
+
f = U8Field.new
|
280
|
+
|
281
|
+
assert_equal 'c', f.pattern
|
282
|
+
assert_equal 1, f.length
|
283
|
+
assert_equal Integer, f.rtype
|
284
|
+
end
|
285
|
+
|
286
|
+
def test_smallint_clean
|
287
|
+
f = U8Field.new
|
288
|
+
|
289
|
+
assert_equal nil, f.clean(0xFF)
|
290
|
+
assert_equal 10, f.clean(10)
|
291
|
+
end
|
292
|
+
|
293
|
+
end
|
294
|
+
|
295
|
+
class TestDoubleField < Test::Unit::TestCase
|
296
|
+
include FieldConformity
|
297
|
+
|
298
|
+
def test_double_conformity
|
299
|
+
f = U16Field.new :name => :foo
|
300
|
+
conform_field!(f)
|
301
|
+
|
302
|
+
assert_method_removed(f, :pattern=)
|
303
|
+
assert_method_removed(f, :length=)
|
304
|
+
end
|
305
|
+
|
306
|
+
def test_double_operation
|
307
|
+
f = U16Field.new
|
308
|
+
|
309
|
+
assert_equal 'n', f.pattern
|
310
|
+
assert_equal 2, f.length
|
311
|
+
assert_equal Integer, f.rtype
|
312
|
+
end
|
313
|
+
|
314
|
+
def test_double_clean
|
315
|
+
f = U16Field.new
|
316
|
+
|
317
|
+
assert_equal nil, f.clean(0xFFFF)
|
318
|
+
assert_equal 10, f.clean(10)
|
319
|
+
end
|
320
|
+
end
|
321
|
+
|
322
|
+
class TestFillerField < Test::Unit::TestCase
|
323
|
+
include FieldConformity
|
324
|
+
|
325
|
+
def test_field_conformity
|
326
|
+
f = Filler.new
|
327
|
+
conform_field!(f)
|
328
|
+
assert_equal "x1", f.pattern
|
329
|
+
end
|
330
|
+
|
331
|
+
def test_filler_does_not_allow_setting_pattern
|
332
|
+
assert_method_removed(Filler.new, :pattern=)
|
333
|
+
end
|
334
|
+
|
335
|
+
def test_pattern_discards_value
|
336
|
+
data = [1,2,3].pack("ccc")
|
337
|
+
filler = Filler.new(:length => 3)
|
338
|
+
unpacked = data.unpack(filler.pattern)
|
339
|
+
assert_equal [], unpacked
|
340
|
+
end
|
341
|
+
|
342
|
+
def test_consume_does_not_touch_stack
|
343
|
+
data = [1,2,3]
|
344
|
+
data.freeze
|
345
|
+
assert_nothing_raised { Filler.new(:length => 1).consume(data) }
|
346
|
+
end
|
347
|
+
|
348
|
+
end
|
349
|
+
|
350
|
+
class TestFieldEmit < Test::Unit::TestCase
|
351
|
+
include FieldConformity
|
352
|
+
|
353
|
+
def test_emit_short
|
354
|
+
f = Field.emit_u8
|
355
|
+
conform_field!(f)
|
356
|
+
|
357
|
+
f = Field.emit_u8(:desc => "Dick length")
|
358
|
+
conform_field!(f)
|
359
|
+
assert_equal "c", f.pattern
|
360
|
+
assert_equal 1, f.length
|
361
|
+
end
|
362
|
+
|
363
|
+
def test_emit_double
|
364
|
+
f = Field.emit_u16
|
365
|
+
conform_field!(f)
|
366
|
+
|
367
|
+
f = Field.emit_u16(:desc => "Dick length")
|
368
|
+
conform_field!(f)
|
369
|
+
assert_equal "n", f.pattern
|
370
|
+
assert_equal 2, f.length
|
371
|
+
end
|
372
|
+
|
373
|
+
def test_emit_char
|
374
|
+
f = Field.emit_char
|
375
|
+
conform_field!(f)
|
376
|
+
|
377
|
+
assert_equal "A1", f.pattern
|
378
|
+
assert_equal 1, f.length
|
379
|
+
|
380
|
+
f = Field.emit_char :length => 3
|
381
|
+
conform_field!(f)
|
382
|
+
|
383
|
+
assert_equal "A3", f.pattern
|
384
|
+
assert_equal 3, f.length
|
385
|
+
end
|
386
|
+
|
387
|
+
def test_emit_float
|
388
|
+
f = Field.emit_r32
|
389
|
+
conform_field!(f)
|
390
|
+
|
391
|
+
assert_equal "g", f.pattern
|
392
|
+
assert_equal 4, f.length
|
393
|
+
end
|
394
|
+
end
|
395
|
+
|
396
|
+
class TestDict < Test::Unit::TestCase
|
397
|
+
|
398
|
+
def test_dict_has_a_fields_array
|
399
|
+
dict_class = Class.new(Dict)
|
400
|
+
assert_respond_to dict_class, :fields
|
401
|
+
assert_equal [], dict_class.fields
|
402
|
+
end
|
403
|
+
|
404
|
+
def test_dict_fields_array_not_class_shared
|
405
|
+
d1, d2 = (0..1).map{|_| Class.new(Dict) }
|
406
|
+
|
407
|
+
d1.fields << 1
|
408
|
+
d2.fields << 2
|
409
|
+
assert_not_equal d1.fields, d2.fields
|
410
|
+
end
|
411
|
+
|
412
|
+
def test_dict_responds_to_emit_methods_from_fields
|
413
|
+
c = Class.new(Dict)
|
414
|
+
|
415
|
+
emitter_methods = Field.methods.grep(/^emit_/)
|
416
|
+
emitter_methods.each do | m |
|
417
|
+
assert_respond_to c, m.gsub(/^emit_/, '')
|
418
|
+
end
|
419
|
+
end
|
420
|
+
|
421
|
+
def test_empty_dict_has_empty_template
|
422
|
+
c = Class.new(Dict)
|
423
|
+
assert_respond_to c, :pattern
|
424
|
+
assert_equal '', c.pattern
|
425
|
+
assert_equal 0, c.length
|
426
|
+
end
|
427
|
+
|
428
|
+
def test_dict_assembles_template
|
429
|
+
c = Class.new(Dict)
|
430
|
+
c.fields << Field.emit_char
|
431
|
+
c.fields << Field.emit_char
|
432
|
+
|
433
|
+
assert_respond_to c, :pattern
|
434
|
+
assert_equal 'A1A1', c.pattern
|
435
|
+
assert_equal 2, c.length
|
436
|
+
end
|
437
|
+
|
438
|
+
end
|
439
|
+
|
440
|
+
class TestDictConsume < Test::Unit::TestCase
|
441
|
+
def test_dict_consume
|
442
|
+
c = Class.new(Dict)
|
443
|
+
c.char :foo
|
444
|
+
c.char :bar
|
445
|
+
|
446
|
+
result = c.consume!(["a", "b"])
|
447
|
+
assert_kind_of c, result
|
448
|
+
|
449
|
+
assert_equal "a", result.foo
|
450
|
+
assert_equal "b", result.bar
|
451
|
+
end
|
452
|
+
end
|
453
|
+
|
454
|
+
class TestDictEmitDSL < Test::Unit::TestCase
|
455
|
+
|
456
|
+
def test_dict_emit_char
|
457
|
+
c = Class.new(Dict)
|
458
|
+
c.char :tag, :desc => "Some name"
|
459
|
+
|
460
|
+
assert c.instance_methods.include?("tag")
|
461
|
+
|
462
|
+
assert_equal 1, c.fields.length
|
463
|
+
field = c.fields[0]
|
464
|
+
|
465
|
+
assert_equal 1, field.length
|
466
|
+
assert_equal "A1", field.pattern
|
467
|
+
assert_equal :tag, field.name
|
468
|
+
end
|
469
|
+
|
470
|
+
def test_dict_emit_char_with_length
|
471
|
+
c = Class.new(Dict)
|
472
|
+
c.char :joe, 3, :desc => "Some name"
|
473
|
+
|
474
|
+
assert c.instance_methods.include?("joe")
|
475
|
+
|
476
|
+
assert_equal 1, c.fields.length
|
477
|
+
field = c.fields[0]
|
478
|
+
assert_equal 3, field.length
|
479
|
+
assert_equal "A3", field.pattern
|
480
|
+
assert_equal :joe, field.name
|
481
|
+
end
|
482
|
+
|
483
|
+
def test_dict_emit_u32
|
484
|
+
c = Class.new(Dict)
|
485
|
+
c.u32 :num, :desc => "Huge number"
|
486
|
+
|
487
|
+
assert c.instance_methods.include?("num")
|
488
|
+
|
489
|
+
assert_equal 1, c.fields.length
|
490
|
+
field = c.fields[0]
|
491
|
+
assert_equal 4, field.length
|
492
|
+
assert_equal "N", field.pattern
|
493
|
+
assert_equal :num, field.name
|
494
|
+
end
|
495
|
+
|
496
|
+
def test_dict_emit_r32
|
497
|
+
c = Class.new(Dict)
|
498
|
+
c.r32 :joe, :req => true
|
499
|
+
|
500
|
+
assert c.instance_methods.include?("joe")
|
501
|
+
|
502
|
+
assert_equal 1, c.fields.length
|
503
|
+
field = c.fields[0]
|
504
|
+
assert_equal 4, field.length
|
505
|
+
assert_equal "g", field.pattern
|
506
|
+
assert_equal true, field.req?
|
507
|
+
end
|
508
|
+
|
509
|
+
def test_dict_emit_u8
|
510
|
+
c = Class.new(Dict)
|
511
|
+
c.u8 :joe, :req => true
|
512
|
+
|
513
|
+
assert c.instance_methods.include?("joe")
|
514
|
+
|
515
|
+
assert_equal 1, c.fields.length
|
516
|
+
|
517
|
+
field = c.fields[0]
|
518
|
+
assert_equal 1, field.length
|
519
|
+
assert_equal "c", field.pattern
|
520
|
+
assert_equal true, field.req?
|
521
|
+
end
|
522
|
+
|
523
|
+
def test_dict_emit_u16
|
524
|
+
c = Class.new(Dict)
|
525
|
+
c.u16 :joe, :req => true, :desc => "A little bit of numbers"
|
526
|
+
|
527
|
+
assert c.instance_methods.include?("joe")
|
528
|
+
|
529
|
+
assert_equal 1, c.fields.length
|
530
|
+
|
531
|
+
field = c.fields[0]
|
532
|
+
|
533
|
+
assert_equal 2, field.length
|
534
|
+
assert_equal "n", field.pattern
|
535
|
+
assert_equal "A little bit of numbers", field.desc
|
536
|
+
end
|
537
|
+
|
538
|
+
def test_dict_emit_array
|
539
|
+
c = Class.new(Dict)
|
540
|
+
c.array :point, :u32, :desc => "Two coordinates"
|
541
|
+
|
542
|
+
assert c.instance_methods.include?("point")
|
543
|
+
|
544
|
+
assert_equal 1, c.fields.length
|
545
|
+
field = c.fields[0]
|
546
|
+
|
547
|
+
assert_kind_of ArrayField, field
|
548
|
+
assert_equal "Two coordinates", field.desc
|
549
|
+
assert_equal 1, field.members.length
|
550
|
+
assert_equal U32Field, field.members[0].class
|
551
|
+
end
|
552
|
+
|
553
|
+
def test_dict_emit_inner
|
554
|
+
c = Class.new(Dict)
|
555
|
+
c2 = Class.new(Dict)
|
556
|
+
|
557
|
+
c.inner :nest, c2, :desc => "Nested struct"
|
558
|
+
|
559
|
+
assert c.instance_methods.include?("nest")
|
560
|
+
|
561
|
+
assert_equal 1, c.fields.length
|
562
|
+
f = c.fields[0]
|
563
|
+
|
564
|
+
assert_kind_of InnerField, f
|
565
|
+
assert_equal "Nested struct", f.desc
|
566
|
+
assert_equal c2, f.cast
|
567
|
+
end
|
568
|
+
|
569
|
+
def test_dict_emit_array_of_substructs
|
570
|
+
c = Class.new(Dict)
|
571
|
+
c2 = Class.new(Dict)
|
572
|
+
|
573
|
+
c2.u32 :some_num
|
574
|
+
c.array :inners, c2, 8, :desc => "Inner items"
|
575
|
+
|
576
|
+
assert c.instance_methods.include?("inners")
|
577
|
+
|
578
|
+
assert_equal 1, c.fields.length
|
579
|
+
f = c.fields[0]
|
580
|
+
|
581
|
+
assert_kind_of ArrayField, f
|
582
|
+
assert_equal "Inner items", f.desc
|
583
|
+
|
584
|
+
assert_equal 8, f.members.length, "8 inner members should be there"
|
585
|
+
|
586
|
+
mem = f.members[0]
|
587
|
+
assert_equal c2, mem.cast
|
588
|
+
end
|
589
|
+
end
|
590
|
+
|
591
|
+
class TestDictCompact < Test::Unit::TestCase
|
592
|
+
def test_only_with_interspersed_fields
|
593
|
+
c = Class.new(Dict) do
|
594
|
+
u8 :some
|
595
|
+
u8 :another
|
596
|
+
u8 :third
|
597
|
+
end
|
598
|
+
|
599
|
+
distill = c.only(:another)
|
600
|
+
|
601
|
+
assert_equal distill.length, c.length, "The distilled struct should occupy the same space"
|
602
|
+
|
603
|
+
assert distill.ancestors.include?(c)
|
604
|
+
assert_equal 3, distill.fields.length
|
605
|
+
|
606
|
+
assert_kind_of Filler, distill.fields[0]
|
607
|
+
assert_equal 1, distill.fields[0].length
|
608
|
+
|
609
|
+
assert_kind_of U8Field, distill.fields[1]
|
610
|
+
assert_equal 1, distill.fields[0].length
|
611
|
+
|
612
|
+
assert_kind_of Filler, distill.fields[2]
|
613
|
+
assert_equal 1, distill.fields[2].length
|
614
|
+
|
615
|
+
end
|
616
|
+
|
617
|
+
def test_only_with_fields_in_a_row
|
618
|
+
c = Class.new(Dict) do
|
619
|
+
u8 :some
|
620
|
+
u32 :another
|
621
|
+
u8 :third
|
622
|
+
u32 :fourth
|
623
|
+
char :fifth, 10
|
624
|
+
end
|
625
|
+
|
626
|
+
distill = c.only(:third)
|
627
|
+
assert_equal distill.length, c.length, "The distilled struct should occupy the same space"
|
628
|
+
assert_equal 3, distill.fields.length
|
629
|
+
|
630
|
+
result = distill.apply!("abcdefhjhjkujkdkklsalierioeiore")
|
631
|
+
|
632
|
+
assert_kind_of Filler, distill.fields[0]
|
633
|
+
assert_equal 5, distill.fields[0].length
|
634
|
+
|
635
|
+
assert_kind_of Filler, distill.fields[2]
|
636
|
+
assert_equal 14, distill.fields[2].length
|
637
|
+
|
638
|
+
assert_nil result.some
|
639
|
+
assert_nil result.fourth
|
640
|
+
end
|
641
|
+
|
642
|
+
def test_get_filler
|
643
|
+
c = Class.new(Dict) do
|
644
|
+
u32 :some
|
645
|
+
end
|
646
|
+
|
647
|
+
filler = c.filler
|
648
|
+
assert_equal filler.length, c.length
|
649
|
+
assert_equal 1, c.fields.length
|
650
|
+
end
|
651
|
+
|
652
|
+
def test_filler_parses_the_same
|
653
|
+
c = Class.new(Dict) do
|
654
|
+
u8 :first
|
655
|
+
u8 :second
|
656
|
+
u8 :third
|
657
|
+
end
|
658
|
+
|
659
|
+
distill = c.only(:second)
|
660
|
+
|
661
|
+
data = [1,2,3].pack("ccc")
|
662
|
+
|
663
|
+
base_r = c.apply!(data)
|
664
|
+
assert_not_nil base_r.first
|
665
|
+
assert_not_nil base_r.third
|
666
|
+
assert_equal 2, base_r.second
|
667
|
+
|
668
|
+
r = distill.apply!(data)
|
669
|
+
assert_nil r.first
|
670
|
+
assert_nil r.third
|
671
|
+
assert_equal 2, r.second
|
672
|
+
end
|
673
|
+
end
|
674
|
+
|
675
|
+
class TestDictApply < Test::Unit::TestCase
|
676
|
+
def test_apply
|
677
|
+
struct = Class.new(Dict) do
|
678
|
+
char :name, "julik".length
|
679
|
+
char :module, "depix".length
|
680
|
+
end
|
681
|
+
|
682
|
+
result = struct.apply!("julikdepix")
|
683
|
+
assert_equal "julik", result.name
|
684
|
+
assert_equal "depix", result.module
|
685
|
+
end
|
686
|
+
end
|