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