8564eb9f7e
The discovery RPC protocol does not yet distinguish TCP and UDP ports. But it can't hurt to do so in our internal model.
160 lines
3.9 KiB
Go
160 lines
3.9 KiB
Go
package discover
|
|
|
|
import (
|
|
logpkg "log"
|
|
"net"
|
|
"os"
|
|
"reflect"
|
|
"testing"
|
|
"time"
|
|
|
|
"github.com/ethereum/go-ethereum/logger"
|
|
)
|
|
|
|
func init() {
|
|
logger.AddLogSystem(logger.NewStdLogSystem(os.Stdout, logpkg.LstdFlags, logger.ErrorLevel))
|
|
}
|
|
|
|
func TestUDP_ping(t *testing.T) {
|
|
t.Parallel()
|
|
|
|
n1, _ := ListenUDP(newkey(), "127.0.0.1:0")
|
|
n2, _ := ListenUDP(newkey(), "127.0.0.1:0")
|
|
defer n1.Close()
|
|
defer n2.Close()
|
|
|
|
if err := n1.net.ping(n2.self); err != nil {
|
|
t.Fatalf("ping error: %v", err)
|
|
}
|
|
if find(n2, n1.self.ID) == nil {
|
|
t.Errorf("node 2 does not contain id of node 1")
|
|
}
|
|
if e := find(n1, n2.self.ID); e != nil {
|
|
t.Errorf("node 1 does contains id of node 2: %v", e)
|
|
}
|
|
}
|
|
|
|
func find(tab *Table, id NodeID) *Node {
|
|
for _, b := range tab.buckets {
|
|
for _, e := range b.entries {
|
|
if e.ID == id {
|
|
return e
|
|
}
|
|
}
|
|
}
|
|
return nil
|
|
}
|
|
|
|
func TestUDP_findnode(t *testing.T) {
|
|
t.Parallel()
|
|
|
|
n1, _ := ListenUDP(newkey(), "127.0.0.1:0")
|
|
n2, _ := ListenUDP(newkey(), "127.0.0.1:0")
|
|
defer n1.Close()
|
|
defer n2.Close()
|
|
|
|
entry := MustParseNode("enode://9d8a19597e312ef32d76e6b4903bb43d7bcd892d17b769d30b404bd3a4c2dca6c86184b17d0fdeeafe3b01e0e912d990ddc853db3f325d5419f31446543c30be@127.0.0.1:54194")
|
|
n2.add([]*Node{entry})
|
|
|
|
target := randomID(n1.self.ID, 100)
|
|
result, _ := n1.net.findnode(n2.self, target)
|
|
if len(result) != 1 {
|
|
t.Fatalf("wrong number of results: got %d, want 1", len(result))
|
|
}
|
|
if !reflect.DeepEqual(result[0], entry) {
|
|
t.Errorf("wrong result: got %v, want %v", result[0], entry)
|
|
}
|
|
}
|
|
|
|
func TestUDP_replytimeout(t *testing.T) {
|
|
t.Parallel()
|
|
|
|
// reserve a port so we don't talk to an existing service by accident
|
|
addr, _ := net.ResolveUDPAddr("udp", "127.0.0.1:0")
|
|
fd, err := net.ListenUDP("udp", addr)
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
defer fd.Close()
|
|
|
|
n1, _ := ListenUDP(newkey(), "127.0.0.1:0")
|
|
defer n1.Close()
|
|
n2 := n1.bumpOrAdd(randomID(n1.self.ID, 10), fd.LocalAddr().(*net.UDPAddr))
|
|
|
|
if err := n1.net.ping(n2); err != errTimeout {
|
|
t.Error("expected timeout error, got", err)
|
|
}
|
|
|
|
if result, err := n1.net.findnode(n2, n1.self.ID); err != errTimeout {
|
|
t.Error("expected timeout error, got", err)
|
|
} else if len(result) > 0 {
|
|
t.Error("expected empty result, got", result)
|
|
}
|
|
}
|
|
|
|
func TestUDP_findnodeMultiReply(t *testing.T) {
|
|
t.Parallel()
|
|
|
|
n1, _ := ListenUDP(newkey(), "127.0.0.1:0")
|
|
n2, _ := ListenUDP(newkey(), "127.0.0.1:0")
|
|
udp2 := n2.net.(*udp)
|
|
defer n1.Close()
|
|
defer n2.Close()
|
|
|
|
nodes := make([]*Node, bucketSize)
|
|
for i := range nodes {
|
|
nodes[i] = &Node{
|
|
IP: net.IP{1, 2, 3, 4},
|
|
DiscPort: i + 1,
|
|
TCPPort: i + 1,
|
|
ID: randomID(n2.self.ID, i+1),
|
|
}
|
|
}
|
|
|
|
// ask N2 for neighbors. it will send an empty reply back.
|
|
// the request will wait for up to bucketSize replies.
|
|
resultC := make(chan []*Node)
|
|
go func() {
|
|
ns, err := n1.net.findnode(n2.self, n1.self.ID)
|
|
if err != nil {
|
|
t.Error("findnode error:", err)
|
|
}
|
|
resultC <- ns
|
|
}()
|
|
|
|
// send a few more neighbors packets to N1.
|
|
// it should collect those.
|
|
for end := 0; end < len(nodes); {
|
|
off := end
|
|
if end = end + 5; end > len(nodes) {
|
|
end = len(nodes)
|
|
}
|
|
udp2.send(n1.self, neighborsPacket, neighbors{
|
|
Nodes: nodes[off:end],
|
|
Expiration: uint64(time.Now().Add(10 * time.Second).Unix()),
|
|
})
|
|
}
|
|
|
|
// check that they are all returned. we cannot just check for
|
|
// equality because they might not be returned in the order they
|
|
// were sent.
|
|
result := <-resultC
|
|
if hasDuplicates(result) {
|
|
t.Error("result slice contains duplicates")
|
|
}
|
|
if len(result) != len(nodes) {
|
|
t.Errorf("wrong number of nodes returned: got %d, want %d", len(result), len(nodes))
|
|
}
|
|
matched := make(map[NodeID]bool)
|
|
for _, n := range result {
|
|
for _, expn := range nodes {
|
|
if n.ID == expn.ID { // && bytes.Equal(n.Addr.IP, expn.Addr.IP) && n.Addr.Port == expn.Addr.Port {
|
|
matched[n.ID] = true
|
|
}
|
|
}
|
|
}
|
|
if len(matched) != len(nodes) {
|
|
t.Errorf("wrong number of matching nodes: got %d, want %d", len(matched), len(nodes))
|
|
}
|
|
}
|