]> Sergey Matveev's repositories - btrtrc.git/blob - bencode/decode_test.go
bencode: Decode singleton lists of the expected type
[btrtrc.git] / bencode / decode_test.go
1 package bencode
2
3 import (
4         "bytes"
5         "io"
6         "math/big"
7         "reflect"
8         "testing"
9
10         "github.com/stretchr/testify/assert"
11         "github.com/stretchr/testify/require"
12 )
13
14 type random_decode_test struct {
15         data     string
16         expected interface{}
17 }
18
19 var random_decode_tests = []random_decode_test{
20         {"i57e", int64(57)},
21         {"i-9223372036854775808e", int64(-9223372036854775808)},
22         {"5:hello", "hello"},
23         {"29:unicode test проверка", "unicode test проверка"},
24         {"d1:ai5e1:b5:helloe", map[string]interface{}{"a": int64(5), "b": "hello"}},
25         {"li5ei10ei15ei20e7:bencodee",
26                 []interface{}{int64(5), int64(10), int64(15), int64(20), "bencode"}},
27         {"ldedee", []interface{}{map[string]interface{}{}, map[string]interface{}{}}},
28         {"le", []interface{}{}},
29         {"i604919719469385652980544193299329427705624352086e", func() *big.Int {
30                 ret, _ := big.NewInt(-1).SetString("604919719469385652980544193299329427705624352086", 10)
31                 return ret
32         }()},
33         {"d1:rd6:\xd4/\xe2F\x00\x01e1:t3:\x9a\x87\x011:v4:TR%=1:y1:re", map[string]interface{}{
34                 "r": map[string]interface{}{},
35                 "t": "\x9a\x87\x01",
36                 "v": "TR%=",
37                 "y": "r",
38         }},
39 }
40
41 func TestRandomDecode(t *testing.T) {
42         for _, test := range random_decode_tests {
43                 var value interface{}
44                 err := Unmarshal([]byte(test.data), &value)
45                 if err != nil {
46                         t.Error(err, test.data)
47                         continue
48                 }
49                 assert.EqualValues(t, test.expected, value)
50         }
51 }
52
53 func TestLoneE(t *testing.T) {
54         var v int
55         err := Unmarshal([]byte("e"), &v)
56         se := err.(*SyntaxError)
57         require.EqualValues(t, 0, se.Offset)
58 }
59
60 func TestDecoderConsecutive(t *testing.T) {
61         d := NewDecoder(bytes.NewReader([]byte("i1ei2e")))
62         var i int
63         err := d.Decode(&i)
64         require.NoError(t, err)
65         require.EqualValues(t, 1, i)
66         err = d.Decode(&i)
67         require.NoError(t, err)
68         require.EqualValues(t, 2, i)
69         err = d.Decode(&i)
70         require.Equal(t, io.EOF, err)
71 }
72
73 func TestDecoderConsecutiveDicts(t *testing.T) {
74         bb := bytes.NewBufferString("d4:herp4:derped3:wat1:ke17:oh baby a triple!")
75
76         d := NewDecoder(bb)
77         assert.EqualValues(t, "d4:herp4:derped3:wat1:ke17:oh baby a triple!", bb.Bytes())
78         assert.EqualValues(t, 0, d.Offset)
79
80         var m map[string]interface{}
81
82         require.NoError(t, d.Decode(&m))
83         assert.Len(t, m, 1)
84         assert.Equal(t, "derp", m["herp"])
85         assert.Equal(t, "d3:wat1:ke17:oh baby a triple!", bb.String())
86         assert.EqualValues(t, 14, d.Offset)
87
88         require.NoError(t, d.Decode(&m))
89         assert.Equal(t, "k", m["wat"])
90         assert.Equal(t, "17:oh baby a triple!", bb.String())
91         assert.EqualValues(t, 24, d.Offset)
92
93         var s string
94         require.NoError(t, d.Decode(&s))
95         assert.Equal(t, "oh baby a triple!", s)
96         assert.EqualValues(t, 44, d.Offset)
97 }
98
99 func check_error(t *testing.T, err error) {
100         if err != nil {
101                 t.Error(err)
102         }
103 }
104
105 func assert_equal(t *testing.T, x, y interface{}) {
106         if !reflect.DeepEqual(x, y) {
107                 t.Errorf("got: %v (%T), expected: %v (%T)\n", x, x, y, y)
108         }
109 }
110
111 type unmarshaler_int struct {
112         x int
113 }
114
115 func (this *unmarshaler_int) UnmarshalBencode(data []byte) error {
116         return Unmarshal(data, &this.x)
117 }
118
119 type unmarshaler_string struct {
120         x string
121 }
122
123 func (this *unmarshaler_string) UnmarshalBencode(data []byte) error {
124         this.x = string(data)
125         return nil
126 }
127
128 func TestUnmarshalerBencode(t *testing.T) {
129         var i unmarshaler_int
130         var ss []unmarshaler_string
131         check_error(t, Unmarshal([]byte("i71e"), &i))
132         assert_equal(t, i.x, 71)
133         check_error(t, Unmarshal([]byte("l5:hello5:fruit3:waye"), &ss))
134         assert_equal(t, ss[0].x, "5:hello")
135         assert_equal(t, ss[1].x, "5:fruit")
136         assert_equal(t, ss[2].x, "3:way")
137
138 }
139
140 func TestIgnoreUnmarshalTypeError(t *testing.T) {
141         s := struct {
142                 Ignore int `bencode:",ignore_unmarshal_type_error"`
143                 Normal int
144         }{}
145         require.Error(t, Unmarshal([]byte("d6:Normal5:helloe"), &s))
146         assert.NoError(t, Unmarshal([]byte("d6:Ignore5:helloe"), &s))
147         require.Nil(t, Unmarshal([]byte("d6:Ignorei42ee"), &s))
148         assert.EqualValues(t, 42, s.Ignore)
149 }
150
151 // Test unmarshalling []byte into something that has the same kind but
152 // different type.
153 func TestDecodeCustomSlice(t *testing.T) {
154         type flag byte
155         var fs3, fs2 []flag
156         // We do a longer slice then a shorter slice to see if the buffers are
157         // shared.
158         d := NewDecoder(bytes.NewBufferString("3:\x01\x10\xff2:\x04\x0f"))
159         require.NoError(t, d.Decode(&fs3))
160         require.NoError(t, d.Decode(&fs2))
161         assert.EqualValues(t, []flag{1, 16, 255}, fs3)
162         assert.EqualValues(t, []flag{4, 15}, fs2)
163 }
164
165 func TestUnmarshalUnusedBytes(t *testing.T) {
166         var i int
167         require.EqualValues(t, ErrUnusedTrailingBytes{1}, Unmarshal([]byte("i42ee"), &i))
168         assert.EqualValues(t, 42, i)
169 }
170
171 func TestUnmarshalByteArray(t *testing.T) {
172         var ba [2]byte
173         assert.NoError(t, Unmarshal([]byte("2:hi"), &ba))
174         assert.EqualValues(t, "hi", ba[:])
175 }