File: packing_test.rb

package info (click to toggle)
ruby-packable 1.3.14-2
  • links: PTS, VCS
  • area: main
  • in suites: bookworm, forky, sid, trixie
  • size: 204 kB
  • sloc: ruby: 609; makefile: 4
file content (141 lines) | stat: -rw-r--r-- 4,625 bytes parent folder | download | duplicates (2)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
require File.expand_path(File.dirname(__FILE__) + '/test_helper')
# Warning: ugly...

class XYZ
  include Packable
  def write_packed(io, options)
    io << "xyz"
  end
  def self.unpack_string(s, options)
    raise "baddly packed XYZ: #{s}" unless "xyz" == s
    XYZ.new
  end
end

class TestingPack < Minitest::Test

  context "Original form" do
    should "pack like before" do
      assert_equal "a  \000\000\000\001", ["a",1,66].pack("A3N")
    end

    should "be equivalent to new form" do
      assert_equal ["a",1,2.34, 66].pack({:bytes=>3}, {:bytes=>4, :endian=>:big}, {:precision=>:double, :endian=>:big}), ["a",1,2.34, 66].pack("A3NG")
    end
  end

  def test_shortcuts
    assert_equal 0x123456.pack(:short), 0x123456.pack(:bytes => 2)
    assert_equal 0x3456, 0x123456.pack(:short).unpack(:short)
  end

  def test_custom_form
    assert_equal "xyz", XYZ.new.pack
    assert_equal XYZ, "xyz".unpack(XYZ).class
  end

  def test_pack_default
    assert_equal "\000\000\000\006", 6.pack
    assert_equal "abcd", "abcd".pack
    assert_equal "\000\000\000\006abcd", [6,"abcd"].pack
    String.packers.set :flv_signature, :bytes => 3, :fill => "FLV"
    assert_equal "xFL", "x".pack(:flv_signature)
  end

  def test_integer
    assert_equal "\002\001\000", 258.pack(:bytes => 3, :endian => :little)
    assert_equal 258, Integer.unpack("\002\001\000", :bytes => 3, :endian => :little)
    assert_equal (1<<24)-1, -1.pack(:bytes => 3).unpack(Integer, :bytes => 3, :signed => false)
    assert_equal -1, -1.pack(:bytes => 3).unpack(Integer, :bytes => 3, :signed => true)
    assert_equal 42, 42.pack('L').unpack(Integer, :bytes => 4, :endian => :native)
    assert_raises(ArgumentError){ 42.pack(:endian => "Geronimo")}
  end

  def test_bignum
    assert_equal 1.pack(:long), ((1 << 69) + 1).pack(:long)
    assert_equal "*" + ("\000" * 15), (42 << (8*15)).pack(:bytes => 16)
    assert_equal 42 << (8*15), (42 << (8*15)).pack(:bytes => 16).unpack(Integer, :bytes => 16)
  end

  def test_float
    assert_raises(ArgumentError){ Math::PI.pack(:endian => "Geronimo")}
    assert_equal Math::PI, Math::PI.pack(:precision => :double, :endian => :native).unpack(Float, :precision => :double, :endian => :native)
    # Issue #1
    assert_equal Math::PI.pack(:precision => :double), Math::PI.pack('G')
    assert_equal Math::PI.pack(:precision => :single), Math::PI.pack('g')
    assert_equal Math::PI.pack(:precision => :double), Math::PI.pack('G')
  end

  def test_io
    io = StringIO.new("\000\000\000\006abcdE!")
    n, s, c = io >> [Integer, {:signed=>false}] >> [String, {:bytes => 4}] >> :char
    assert_equal 6, n
    assert_equal "abcd", s
    assert_equal 69, c
    assert_equal "!", io.read
  end

  def test_io_read_nil
    # library was failing to call read_without_packing when invoked with nil.
    io = StringIO.new("should read(nil)")
    assert_equal "should read(nil)", io.read(nil)
  end

  def test_io_read_to_outbuf
    # library was failing to call read_without_packing when invoked with fixnum and output buffer.
    io = StringIO.new("should read(fixnum, buf)")
    io.read(11, outbuf='')
    assert_equal "should read", outbuf
  end

  should "do basic type checking" do
    assert_raises(TypeError) {"".unpack(42, :short)}
  end

  context "Reading beyond the eof" do
    should "raises an EOFError when reading" do
      ["", "x"].each do |s|
        io = StringIO.new(s)
        assert_raises(EOFError) {io.read(:double)}
        assert_raises(EOFError) {io.read(:short)}
        assert_raises(EOFError) {io.read(String, :bytes => 4)}
      end
    end

    should "return nil for unpacking" do
      assert_nil "".unpack(:double)
      assert_nil "".unpack(:short)
      assert_nil "x".unpack(:double)
      assert_nil "x".unpack(:short)
    end
  end

  context "Filters" do
    context "for Object" do
      Object.packers.set :generic_class_writer do |packer|
        packer.write do |io|
          io << self.class.name << self
        end
      end
      should "be follow accessible everywhere" do
        assert_equal "StringHello", "Hello".pack(:generic_class_writer)
        assert_match /Integer\x00\x00\x00\x06$/, 6.pack(:generic_class_writer)
      end
    end
    context "for a specific class" do
      String.packers.set :specific_writer do |packer|
        packer.write do |io|
          io << "Hello"
        end
      end

      should "be accessible only from that class and descendants" do
        assert_equal "Hello", "World".pack(:specific_writer)
        assert_raises RuntimeError do
          6.pack(:specific_writer)
        end
      end
    end
  end

end