github.com/anacrolix/torrent@v1.61.0/bencode/decode_test.go (about) 1 package bencode 2 3 import ( 4 "bytes" 5 "encoding/json" 6 "fmt" 7 "io" 8 "math/big" 9 "reflect" 10 "strings" 11 "testing" 12 13 qt "github.com/go-quicktest/qt" 14 "github.com/stretchr/testify/assert" 15 "github.com/stretchr/testify/require" 16 ) 17 18 type random_decode_test struct { 19 data string 20 expected interface{} 21 } 22 23 var random_decode_tests = []random_decode_test{ 24 {"i57e", int64(57)}, 25 {"i-9223372036854775808e", int64(-9223372036854775808)}, 26 {"5:hello", "hello"}, 27 {"29:unicode test проверка", "unicode test проверка"}, 28 {"d1:ai5e1:b5:helloe", map[string]interface{}{"a": int64(5), "b": "hello"}}, 29 { 30 "li5ei10ei15ei20e7:bencodee", 31 []interface{}{int64(5), int64(10), int64(15), int64(20), "bencode"}, 32 }, 33 {"ldedee", []interface{}{map[string]interface{}{}, map[string]interface{}{}}}, 34 {"le", []interface{}{}}, 35 {"i604919719469385652980544193299329427705624352086e", func() *big.Int { 36 ret, _ := big.NewInt(-1).SetString("604919719469385652980544193299329427705624352086", 10) 37 return ret 38 }()}, 39 {"d1:rd6:\xd4/\xe2F\x00\x01i42ee1:t3:\x9a\x87\x011:v4:TR%=1:y1:re", map[string]interface{}{ 40 "r": map[string]interface{}{"\xd4/\xe2F\x00\x01": int64(42)}, 41 "t": "\x9a\x87\x01", 42 "v": "TR%=", 43 "y": "r", 44 }}, 45 {"d0:i420ee", map[string]interface{}{"": int64(420)}}, 46 } 47 48 func TestRandomDecode(t *testing.T) { 49 for _, test := range random_decode_tests { 50 var value interface{} 51 err := Unmarshal([]byte(test.data), &value) 52 if err != nil { 53 t.Error(err, test.data) 54 continue 55 } 56 assert.EqualValues(t, test.expected, value) 57 } 58 } 59 60 func TestLoneE(t *testing.T) { 61 var v int 62 err := Unmarshal([]byte("e"), &v) 63 se := err.(*SyntaxError) 64 require.EqualValues(t, 0, se.Offset) 65 } 66 67 func TestDecoderConsecutive(t *testing.T) { 68 d := NewDecoder(bytes.NewReader([]byte("i1ei2e"))) 69 var i int 70 err := d.Decode(&i) 71 require.NoError(t, err) 72 require.EqualValues(t, 1, i) 73 err = d.Decode(&i) 74 require.NoError(t, err) 75 require.EqualValues(t, 2, i) 76 err = d.Decode(&i) 77 require.Equal(t, io.EOF, err) 78 } 79 80 func TestDecoderConsecutiveDicts(t *testing.T) { 81 bb := bytes.NewBufferString("d4:herp4:derped3:wat1:ke17:oh baby a triple!") 82 83 d := NewDecoder(bb) 84 assert.EqualValues(t, "d4:herp4:derped3:wat1:ke17:oh baby a triple!", bb.Bytes()) 85 assert.EqualValues(t, 0, d.Offset) 86 87 var m map[string]interface{} 88 89 require.NoError(t, d.Decode(&m)) 90 assert.Len(t, m, 1) 91 assert.Equal(t, "derp", m["herp"]) 92 assert.Equal(t, "d3:wat1:ke17:oh baby a triple!", bb.String()) 93 assert.EqualValues(t, 14, d.Offset) 94 95 require.NoError(t, d.Decode(&m)) 96 assert.Equal(t, "k", m["wat"]) 97 assert.Equal(t, "17:oh baby a triple!", bb.String()) 98 assert.EqualValues(t, 24, d.Offset) 99 100 var s string 101 require.NoError(t, d.Decode(&s)) 102 assert.Equal(t, "oh baby a triple!", s) 103 assert.EqualValues(t, 44, d.Offset) 104 } 105 106 func check_error(t *testing.T, err error) { 107 if err != nil { 108 t.Error(err) 109 } 110 } 111 112 func assert_equal(t *testing.T, x, y interface{}) { 113 if !reflect.DeepEqual(x, y) { 114 t.Errorf("got: %v (%T), expected: %v (%T)\n", x, x, y, y) 115 } 116 } 117 118 type unmarshalerInt struct { 119 x int 120 } 121 122 func (me *unmarshalerInt) UnmarshalBencode(data []byte) error { 123 return Unmarshal(data, &me.x) 124 } 125 126 type unmarshalerString struct { 127 x string 128 } 129 130 func (me *unmarshalerString) UnmarshalBencode(data []byte) error { 131 me.x = string(data) 132 return nil 133 } 134 135 func TestUnmarshalerBencode(t *testing.T) { 136 var i unmarshalerInt 137 var ss []unmarshalerString 138 check_error(t, Unmarshal([]byte("i71e"), &i)) 139 assert_equal(t, i.x, 71) 140 check_error(t, Unmarshal([]byte("l5:hello5:fruit3:waye"), &ss)) 141 assert_equal(t, ss[0].x, "5:hello") 142 assert_equal(t, ss[1].x, "5:fruit") 143 assert_equal(t, ss[2].x, "3:way") 144 } 145 146 func TestIgnoreUnmarshalTypeError(t *testing.T) { 147 s := struct { 148 Ignore int `bencode:",ignore_unmarshal_type_error"` 149 Normal int 150 }{} 151 require.Error(t, Unmarshal([]byte("d6:Normal5:helloe"), &s)) 152 assert.NoError(t, Unmarshal([]byte("d6:Ignore5:helloe"), &s)) 153 qt.Assert(t, qt.IsNil(Unmarshal([]byte("d6:Ignorei42ee"), &s))) 154 assert.EqualValues(t, 42, s.Ignore) 155 } 156 157 // Test unmarshalling []byte into something that has the same kind but 158 // different type. 159 func TestDecodeCustomSlice(t *testing.T) { 160 type flag byte 161 var fs3, fs2 []flag 162 // We do a longer slice then a shorter slice to see if the buffers are 163 // shared. 164 d := NewDecoder(bytes.NewBufferString("3:\x01\x10\xff2:\x04\x0f")) 165 require.NoError(t, d.Decode(&fs3)) 166 require.NoError(t, d.Decode(&fs2)) 167 assert.EqualValues(t, []flag{1, 16, 255}, fs3) 168 assert.EqualValues(t, []flag{4, 15}, fs2) 169 } 170 171 func TestUnmarshalUnusedBytes(t *testing.T) { 172 var i int 173 require.EqualValues(t, ErrUnusedTrailingBytes{1}, Unmarshal([]byte("i42ee"), &i)) 174 assert.EqualValues(t, 42, i) 175 } 176 177 func TestUnmarshalByteArray(t *testing.T) { 178 var ba [2]byte 179 assert.NoError(t, Unmarshal([]byte("2:hi"), &ba)) 180 assert.EqualValues(t, "hi", ba[:]) 181 } 182 183 func TestDecodeDictIntoUnsupported(t *testing.T) { 184 // Any type that a dict shouldn't be unmarshallable into. 185 var i int 186 err := Unmarshal([]byte("d1:a1:be"), &i) 187 t.Log(err) 188 qt.Check(t, qt.IsNotNil(err)) 189 } 190 191 func TestUnmarshalDictKeyNotString(t *testing.T) { 192 // Any type that a dict shouldn't be unmarshallable into. 193 var i int 194 err := Unmarshal([]byte("di42e3:yese"), &i) 195 t.Log(err) 196 qt.Check(t, qt.IsNotNil(err)) 197 } 198 199 type arbitraryReader struct{} 200 201 func (arbitraryReader) Read(b []byte) (int, error) { 202 return len(b), nil 203 } 204 205 func decodeHugeString(t *testing.T, strLen int64, header, tail string, v interface{}, maxStrLen MaxStrLen) error { 206 r, w := io.Pipe() 207 go func() { 208 fmt.Fprintf(w, header, strLen) 209 io.CopyN(w, arbitraryReader{}, strLen) 210 w.Write([]byte(tail)) 211 w.Close() 212 }() 213 d := NewDecoder(r) 214 d.MaxStrLen = maxStrLen 215 return d.Decode(v) 216 } 217 218 // Ensure that bencode strings in various places obey the Decoder.MaxStrLen field. 219 func TestDecodeMaxStrLen(t *testing.T) { 220 t.Parallel() 221 test := func(header, tail string, v interface{}, maxStrLen MaxStrLen) { 222 strLen := maxStrLen 223 if strLen == 0 { 224 strLen = DefaultDecodeMaxStrLen 225 } 226 qt.Assert(t, qt.IsNil(decodeHugeString(t, strLen, header, tail, v, maxStrLen))) 227 qt.Assert(t, qt.IsNotNil(decodeHugeString(t, strLen+1, header, tail, v, maxStrLen))) 228 } 229 test("d%d:", "i0ee", new(interface{}), 0) 230 test("%d:", "", new(interface{}), DefaultDecodeMaxStrLen) 231 test("%d:", "", new([]byte), 1) 232 test("d3:420%d:", "e", new(struct { 233 Hi []byte `bencode:"420"` 234 }), 69) 235 } 236 237 // This is for the "github.com/anacrolix/torrent/metainfo".Info.Private field. 238 func TestDecodeStringIntoBoolPtr(t *testing.T) { 239 var m struct { 240 Private *bool `bencode:"private,omitempty"` 241 } 242 check := func(msg string, expectNil, expectTrue bool) { 243 m.Private = nil 244 qt.Check(t, qt.IsNil(Unmarshal([]byte(msg), &m)), qt.Commentf("%q", msg)) 245 if expectNil { 246 qt.Check(t, qt.IsNil(m.Private)) 247 } else { 248 if qt.Check(t, qt.IsNotNil(m.Private), qt.Commentf("%q", msg)) { 249 qt.Check(t, qt.Equals(*m.Private, expectTrue), qt.Commentf("%q", msg)) 250 } 251 } 252 } 253 check("d7:privatei1ee", false, true) 254 check("d7:privatei0ee", false, false) 255 check("d7:privatei42ee", false, true) 256 // This is a weird case. We could not allocate the bool to indicate it was bad (maybe a bad 257 // serializer which isn't uncommon), but that requires reworking the decoder to handle 258 // automatically. I think if we cared enough we'd create a custom Unmarshaler. Also if we were 259 // worried enough about performance I'd completely rewrite this package. 260 check("d7:private0:e", false, false) 261 check("d7:private1:te", false, true) 262 check("d7:private5:falsee", false, false) 263 check("d7:private1:Fe", false, false) 264 check("d7:private11:bunnyfoofooe", false, true) 265 } 266 267 // To set expectations about how our Decoder should work. 268 func TestJsonDecoderBehaviour(t *testing.T) { 269 test := func(input string, items int, finalErr error) { 270 d := json.NewDecoder(strings.NewReader(input)) 271 actualItems := 0 272 var firstErr error 273 for { 274 var discard any 275 firstErr = d.Decode(&discard) 276 if firstErr != nil { 277 break 278 } 279 actualItems++ 280 } 281 qt.Check(t, qt.Equals(firstErr, finalErr)) 282 qt.Check(t, qt.Equals(actualItems, items)) 283 } 284 test("", 0, io.EOF) 285 test("{}", 1, io.EOF) 286 test("{} {", 1, io.ErrUnexpectedEOF) 287 }