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/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