232 lines
6.6 KiB
Go
232 lines
6.6 KiB
Go
package mainline
|
|
|
|
import (
|
|
"bytes"
|
|
"net"
|
|
"reflect"
|
|
"testing"
|
|
|
|
"github.com/anacrolix/torrent/bencode"
|
|
)
|
|
|
|
var codecTest_validInstances = []struct {
|
|
data []byte
|
|
msg Message
|
|
}{
|
|
// ping Query:
|
|
{
|
|
data: []byte("d1:ad2:id20:abcdefghij0123456789e1:q4:ping1:t2:aa1:y1:qe"),
|
|
msg: Message{
|
|
T: []byte("aa"),
|
|
Y: "q",
|
|
Q: "ping",
|
|
A: QueryArguments{
|
|
ID: []byte("abcdefghij0123456789"),
|
|
},
|
|
},
|
|
},
|
|
// ping or announce_peer Response:
|
|
// Also, includes NUL and EOT characters as transaction ID (`t`).
|
|
{
|
|
data: []byte("d1:rd2:id20:mnopqrstuvwxyz123456e1:t2:\x00\x041:y1:re"),
|
|
msg: Message{
|
|
T: []byte("\x00\x04"),
|
|
Y: "r",
|
|
R: ResponseValues{
|
|
ID: []byte("mnopqrstuvwxyz123456"),
|
|
},
|
|
},
|
|
},
|
|
// find_node Query:
|
|
{
|
|
data: []byte("d1:ad2:id20:abcdefghij01234567896:target20:mnopqrstuvwxyz123456e1:q9:find_node1:t2:\x09\x0a1:y1:qe"),
|
|
msg: Message{
|
|
T: []byte("\x09\x0a"),
|
|
Y: "q",
|
|
Q: "find_node",
|
|
A: QueryArguments{
|
|
ID: []byte("abcdefghij0123456789"),
|
|
Target: []byte("mnopqrstuvwxyz123456"),
|
|
},
|
|
},
|
|
},
|
|
// find_node Response with no nodes (`nodes` key still exists):
|
|
{
|
|
data: []byte("d1:rd2:id20:0123456789abcdefghij5:nodes0:e1:t2:aa1:y1:re"),
|
|
msg: Message{
|
|
T: []byte("aa"),
|
|
Y: "r",
|
|
R: ResponseValues{
|
|
ID: []byte("0123456789abcdefghij"),
|
|
Nodes: []CompactNodeInfo{},
|
|
},
|
|
},
|
|
},
|
|
// find_node Response with a single node:
|
|
{
|
|
data: []byte("d1:rd2:id20:0123456789abcdefghij5:nodes26:abcdefghijklmnopqrst\x8b\x82\x8e\xf5\x0cae1:t2:aa1:y1:re"),
|
|
msg: Message{
|
|
T: []byte("aa"),
|
|
Y: "r",
|
|
R: ResponseValues{
|
|
ID: []byte("0123456789abcdefghij"),
|
|
Nodes: []CompactNodeInfo{
|
|
{
|
|
ID: []byte("abcdefghijklmnopqrst"),
|
|
Addr: net.UDPAddr{IP: []byte("\x8b\x82\x8e\xf5"), Port: 3169, Zone: ""},
|
|
},
|
|
},
|
|
},
|
|
},
|
|
},
|
|
// find_node Response with 8 nodes (all the same except the very last one):
|
|
{
|
|
data: []byte("d1:rd2:id20:0123456789abcdefghij5:nodes208:abcdefghijklmnopqrst\x8b\x82\x8e\xf5\x0caabcdefghijklmnopqrst\x8b\x82\x8e\xf5\x0caabcdefghijklmnopqrst\x8b\x82\x8e\xf5\x0caabcdefghijklmnopqrst\x8b\x82\x8e\xf5\x0caabcdefghijklmnopqrst\x8b\x82\x8e\xf5\x0caabcdefghijklmnopqrst\x8b\x82\x8e\xf5\x0caabcdefghijklmnopqrst\x8b\x82\x8e\xf5\x0cazyxwvutsrqponmlkjihg\xf5\x8e\x82\x8b\x1b\x13e1:t2:aa1:y1:re"),
|
|
msg: Message{
|
|
T: []byte("aa"),
|
|
Y: "r",
|
|
R: ResponseValues{
|
|
ID: []byte("0123456789abcdefghij"),
|
|
Nodes: []CompactNodeInfo{
|
|
{
|
|
ID: []byte("abcdefghijklmnopqrst"),
|
|
Addr: net.UDPAddr{IP: []byte("\x8b\x82\x8e\xf5"), Port: 3169, Zone: ""},
|
|
},
|
|
{
|
|
ID: []byte("abcdefghijklmnopqrst"),
|
|
Addr: net.UDPAddr{IP: []byte("\x8b\x82\x8e\xf5"), Port: 3169, Zone: ""},
|
|
},
|
|
{
|
|
ID: []byte("abcdefghijklmnopqrst"),
|
|
Addr: net.UDPAddr{IP: []byte("\x8b\x82\x8e\xf5"), Port: 3169, Zone: ""},
|
|
},
|
|
{
|
|
ID: []byte("abcdefghijklmnopqrst"),
|
|
Addr: net.UDPAddr{IP: []byte("\x8b\x82\x8e\xf5"), Port: 3169, Zone: ""},
|
|
},
|
|
{
|
|
ID: []byte("abcdefghijklmnopqrst"),
|
|
Addr: net.UDPAddr{IP: []byte("\x8b\x82\x8e\xf5"), Port: 3169, Zone: ""},
|
|
},
|
|
{
|
|
ID: []byte("abcdefghijklmnopqrst"),
|
|
Addr: net.UDPAddr{IP: []byte("\x8b\x82\x8e\xf5"), Port: 3169, Zone: ""},
|
|
},
|
|
{
|
|
ID: []byte("abcdefghijklmnopqrst"),
|
|
Addr: net.UDPAddr{IP: []byte("\x8b\x82\x8e\xf5"), Port: 3169, Zone: ""},
|
|
},
|
|
{
|
|
ID: []byte("zyxwvutsrqponmlkjihg"),
|
|
Addr: net.UDPAddr{IP: []byte("\xf5\x8e\x82\x8b"), Port: 6931, Zone: ""},
|
|
},
|
|
},
|
|
},
|
|
},
|
|
},
|
|
// get_peers Query:
|
|
{
|
|
data: []byte("d1:ad2:id20:abcdefghij01234567899:info_hash20:mnopqrstuvwxyz123456e1:q9:get_peers1:t2:aa1:y1:qe"),
|
|
msg: Message{
|
|
T: []byte("aa"),
|
|
Y: "q",
|
|
Q: "get_peers",
|
|
A: QueryArguments{
|
|
ID: []byte("abcdefghij0123456789"),
|
|
InfoHash: []byte("mnopqrstuvwxyz123456"),
|
|
},
|
|
},
|
|
},
|
|
// get_peers Response with 2 peers (`values`):
|
|
{
|
|
data: []byte("d1:rd2:id20:abcdefghij01234567895:token8:aoeusnth6:valuesl6:axje.u6:idhtnmee1:t2:aa1:y1:re"),
|
|
msg: Message{
|
|
T: []byte("aa"),
|
|
Y: "r",
|
|
R: ResponseValues{
|
|
ID: []byte("abcdefghij0123456789"),
|
|
Token: []byte("aoeusnth"),
|
|
Values: []CompactPeer{
|
|
{IP: []byte("axje"), Port: 11893},
|
|
{IP: []byte("idht"), Port: 28269},
|
|
},
|
|
},
|
|
},
|
|
},
|
|
// get_peers Response with 2 closest nodes (`nodes`):
|
|
{
|
|
data: []byte("d1:rd2:id20:abcdefghij01234567895:nodes52:abcdefghijklmnopqrst\x8b\x82\x8e\xf5\x0cazyxwvutsrqponmlkjihg\xf5\x8e\x82\x8b\x1b\x135:token8:aoeusnthe1:t2:aa1:y1:re"),
|
|
msg: Message{
|
|
T: []byte("aa"),
|
|
Y: "r",
|
|
R: ResponseValues{
|
|
ID: []byte("abcdefghij0123456789"),
|
|
Token: []byte("aoeusnth"),
|
|
Nodes: []CompactNodeInfo{
|
|
{
|
|
ID: []byte("abcdefghijklmnopqrst"),
|
|
Addr: net.UDPAddr{IP: []byte("\x8b\x82\x8e\xf5"), Port: 3169, Zone: ""},
|
|
},
|
|
{
|
|
ID: []byte("zyxwvutsrqponmlkjihg"),
|
|
Addr: net.UDPAddr{IP: []byte("\xf5\x8e\x82\x8b"), Port: 6931, Zone: ""},
|
|
},
|
|
},
|
|
},
|
|
},
|
|
},
|
|
// announce_peer Query without optional `implied_port` argument:
|
|
{
|
|
data: []byte("d1:ad2:id20:abcdefghij01234567899:info_hash20:mnopqrstuvwxyz1234564:porti6881e5:token8:aoeusnthe1:q13:announce_peer1:t2:aa1:y1:qe"),
|
|
msg: Message{
|
|
T: []byte("aa"),
|
|
Y: "q",
|
|
Q: "announce_peer",
|
|
A: QueryArguments{
|
|
ID: []byte("abcdefghij0123456789"),
|
|
InfoHash: []byte("mnopqrstuvwxyz123456"),
|
|
Port: 6881,
|
|
Token: []byte("aoeusnth"),
|
|
},
|
|
},
|
|
},
|
|
{
|
|
data: []byte("d1:eli201e23:A Generic Error Ocurrede1:t2:aa1:y1:ee"),
|
|
msg: Message{
|
|
T: []byte("aa"),
|
|
Y: "e",
|
|
E: Error{Code: 201, Message: []byte("A Generic Error Ocurred")},
|
|
},
|
|
},
|
|
// TODO: Test Error where E.Message is an empty string, and E.Message contains invalid Unicode characters.
|
|
// TODO: Add announce_peer Query with optional `implied_port` argument.
|
|
}
|
|
|
|
func TestUnmarshal(t *testing.T) {
|
|
for i, instance := range codecTest_validInstances {
|
|
msg := Message{}
|
|
err := bencode.Unmarshal(instance.data, &msg)
|
|
if err != nil {
|
|
t.Errorf("Error while unmarshalling valid data #%d: %v", i+1, err)
|
|
continue
|
|
}
|
|
if reflect.DeepEqual(msg, instance.msg) != true {
|
|
t.Errorf("Valid data #%d unmarshalled wrong!\n\tGot : %+v\n\tExpected: %+v",
|
|
i+1, msg, instance.msg)
|
|
}
|
|
}
|
|
}
|
|
|
|
func TestMarshal(t *testing.T) {
|
|
for i, instance := range codecTest_validInstances {
|
|
data, err := bencode.Marshal(instance.msg)
|
|
if err != nil {
|
|
t.Errorf("Error while marshalling valid msg #%d: %v", i+1, err)
|
|
}
|
|
if bytes.Equal(data, instance.data) != true {
|
|
t.Errorf("Valid msg #%d marshalled wrong!\n\tGot : %q\n\tExpected: %q",
|
|
i+1, data, instance.data)
|
|
}
|
|
}
|
|
}
|