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  }