2019-09-25 13:58:19 +00:00
|
|
|
package yggdrasil
|
|
|
|
|
|
|
|
import (
|
2019-09-25 18:07:36 +00:00
|
|
|
"bytes"
|
|
|
|
"math/rand"
|
2019-09-25 13:58:19 +00:00
|
|
|
"os"
|
|
|
|
"testing"
|
2019-09-25 18:07:36 +00:00
|
|
|
"time"
|
2019-09-25 13:58:19 +00:00
|
|
|
|
|
|
|
"github.com/gologme/log"
|
|
|
|
|
|
|
|
"github.com/yggdrasil-network/yggdrasil-go/src/config"
|
|
|
|
)
|
|
|
|
|
|
|
|
// GenerateConfig is modification
|
|
|
|
func GenerateConfig() *config.NodeConfig {
|
|
|
|
cfg := config.GenerateConfig()
|
|
|
|
cfg.AdminListen = "none"
|
|
|
|
cfg.Listen = []string{"tcp://127.0.0.1:0"}
|
|
|
|
cfg.IfName = "none"
|
|
|
|
|
|
|
|
return cfg
|
|
|
|
}
|
|
|
|
|
2019-09-28 12:24:54 +00:00
|
|
|
func GetLoggerWithPrefix(prefix string, verbose bool) *log.Logger {
|
2019-09-25 13:58:19 +00:00
|
|
|
l := log.New(os.Stderr, prefix, log.Flags())
|
2019-09-28 12:24:54 +00:00
|
|
|
if !verbose {
|
|
|
|
return l
|
|
|
|
}
|
2019-09-25 13:58:19 +00:00
|
|
|
l.EnableLevel("info")
|
|
|
|
l.EnableLevel("warn")
|
|
|
|
l.EnableLevel("error")
|
|
|
|
return l
|
|
|
|
}
|
|
|
|
|
2019-09-28 12:24:54 +00:00
|
|
|
func CreateAndConnectTwo(t testing.TB, verbose bool) (*Core, *Core) {
|
2019-09-25 13:58:19 +00:00
|
|
|
nodeA := Core{}
|
2019-09-28 12:24:54 +00:00
|
|
|
_, err := nodeA.Start(GenerateConfig(), GetLoggerWithPrefix("A: ", verbose))
|
2019-09-25 13:58:19 +00:00
|
|
|
if err != nil {
|
|
|
|
t.Fatal(err)
|
|
|
|
}
|
|
|
|
|
|
|
|
nodeB := Core{}
|
2019-09-28 12:24:54 +00:00
|
|
|
_, err = nodeB.Start(GenerateConfig(), GetLoggerWithPrefix("B: ", verbose))
|
2019-09-25 13:58:19 +00:00
|
|
|
if err != nil {
|
|
|
|
t.Fatal(err)
|
|
|
|
}
|
|
|
|
|
|
|
|
err = nodeB.AddPeer("tcp://"+nodeA.link.tcp.getAddr().String(), "")
|
|
|
|
if err != nil {
|
|
|
|
t.Fatal(err)
|
|
|
|
}
|
2019-09-25 18:07:36 +00:00
|
|
|
|
|
|
|
if l := len(nodeA.GetPeers()); l != 1 {
|
|
|
|
t.Fatal("unexpected number of peers", l)
|
|
|
|
}
|
|
|
|
if l := len(nodeB.GetPeers()); l != 1 {
|
|
|
|
t.Fatal("unexpected number of peers", l)
|
|
|
|
}
|
|
|
|
|
|
|
|
return &nodeA, &nodeB
|
|
|
|
}
|
|
|
|
|
2019-09-28 12:10:17 +00:00
|
|
|
// WaitConnected blocks until either nodes negotiated DHT or 5 seconds passed.
|
|
|
|
func WaitConnected(nodeA, nodeB *Core) bool {
|
|
|
|
// It may take up to 3 seconds, but let's wait 5.
|
|
|
|
for i := 0; i < 50; i++ {
|
|
|
|
time.Sleep(100 * time.Millisecond)
|
|
|
|
if len(nodeA.GetSwitchPeers()) > 0 && len(nodeB.GetSwitchPeers()) > 0 {
|
|
|
|
return true
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return false
|
|
|
|
}
|
|
|
|
|
2019-09-25 18:07:36 +00:00
|
|
|
func TestCore_Start_Connect(t *testing.T) {
|
2019-09-28 12:24:54 +00:00
|
|
|
CreateAndConnectTwo(t, true)
|
2019-09-25 18:07:36 +00:00
|
|
|
}
|
|
|
|
|
2019-09-28 12:20:57 +00:00
|
|
|
func CreateEchoListener(t testing.TB, nodeA *Core, bufLen int, repeats int) chan struct{} {
|
2019-09-25 18:07:36 +00:00
|
|
|
// Listen
|
|
|
|
listener, err := nodeA.ConnListen()
|
|
|
|
if err != nil {
|
|
|
|
t.Fatal(err)
|
|
|
|
}
|
|
|
|
|
|
|
|
done := make(chan struct{})
|
|
|
|
go func() {
|
2019-09-28 12:10:17 +00:00
|
|
|
defer listener.Close()
|
2019-09-25 18:07:36 +00:00
|
|
|
conn, err := listener.Accept()
|
|
|
|
if err != nil {
|
|
|
|
t.Error(err)
|
|
|
|
return
|
|
|
|
}
|
|
|
|
defer conn.Close()
|
2019-09-28 12:10:17 +00:00
|
|
|
buf := make([]byte, bufLen)
|
2019-09-28 12:20:57 +00:00
|
|
|
|
|
|
|
for i := 0; i < repeats; i++ {
|
|
|
|
n, err := conn.Read(buf)
|
|
|
|
if err != nil {
|
|
|
|
t.Error(err)
|
|
|
|
return
|
|
|
|
}
|
|
|
|
if n != bufLen {
|
|
|
|
t.Error("missing data")
|
|
|
|
return
|
|
|
|
}
|
|
|
|
_, err = conn.Write(buf)
|
|
|
|
if err != nil {
|
|
|
|
t.Error(err)
|
|
|
|
}
|
2019-09-25 18:07:36 +00:00
|
|
|
}
|
|
|
|
done <- struct{}{}
|
|
|
|
}()
|
|
|
|
|
2019-09-28 12:10:17 +00:00
|
|
|
return done
|
|
|
|
}
|
|
|
|
|
|
|
|
func TestCore_Start_Transfer(t *testing.T) {
|
2019-09-28 12:24:54 +00:00
|
|
|
nodeA, nodeB := CreateAndConnectTwo(t, true)
|
2019-09-28 12:10:17 +00:00
|
|
|
|
|
|
|
msgLen := 1500
|
2019-09-28 12:20:57 +00:00
|
|
|
done := CreateEchoListener(t, nodeA, msgLen, 1)
|
2019-09-28 12:10:17 +00:00
|
|
|
|
|
|
|
if !WaitConnected(nodeA, nodeB) {
|
|
|
|
t.Fatal("nodes did not connect")
|
|
|
|
}
|
|
|
|
|
2019-09-25 18:07:36 +00:00
|
|
|
// Dial
|
|
|
|
dialer, err := nodeB.ConnDialer()
|
|
|
|
if err != nil {
|
|
|
|
t.Fatal(err)
|
|
|
|
}
|
|
|
|
conn, err := dialer.Dial("nodeid", nodeA.NodeID().String())
|
|
|
|
if err != nil {
|
|
|
|
t.Fatal(err)
|
|
|
|
}
|
|
|
|
defer conn.Close()
|
2019-09-28 12:10:17 +00:00
|
|
|
msg := make([]byte, msgLen)
|
2019-09-25 18:07:36 +00:00
|
|
|
rand.Read(msg)
|
|
|
|
conn.Write(msg)
|
|
|
|
if err != nil {
|
|
|
|
t.Fatal(err)
|
|
|
|
}
|
2019-09-28 12:10:17 +00:00
|
|
|
buf := make([]byte, msgLen)
|
2019-09-25 18:07:36 +00:00
|
|
|
_, err = conn.Read(buf)
|
|
|
|
if err != nil {
|
|
|
|
t.Fatal(err)
|
|
|
|
}
|
|
|
|
if bytes.Compare(msg, buf) != 0 {
|
|
|
|
t.Fatal("expected echo")
|
|
|
|
}
|
|
|
|
<-done
|
2019-09-25 13:58:19 +00:00
|
|
|
}
|
2019-09-28 12:20:57 +00:00
|
|
|
|
|
|
|
func BenchmarkCore_Start_Transfer(b *testing.B) {
|
2019-09-28 12:24:54 +00:00
|
|
|
nodeA, nodeB := CreateAndConnectTwo(b, false)
|
2019-09-28 12:20:57 +00:00
|
|
|
|
|
|
|
msgLen := 1500 // typical MTU
|
|
|
|
done := CreateEchoListener(b, nodeA, msgLen, b.N)
|
|
|
|
|
|
|
|
if !WaitConnected(nodeA, nodeB) {
|
|
|
|
b.Fatal("nodes did not connect")
|
|
|
|
}
|
|
|
|
|
|
|
|
// Dial
|
|
|
|
dialer, err := nodeB.ConnDialer()
|
|
|
|
if err != nil {
|
|
|
|
b.Fatal(err)
|
|
|
|
}
|
|
|
|
conn, err := dialer.Dial("nodeid", nodeA.NodeID().String())
|
|
|
|
if err != nil {
|
|
|
|
b.Fatal(err)
|
|
|
|
}
|
|
|
|
defer conn.Close()
|
|
|
|
msg := make([]byte, msgLen)
|
|
|
|
rand.Read(msg)
|
|
|
|
buf := make([]byte, msgLen)
|
|
|
|
|
|
|
|
b.SetBytes(int64(b.N * msgLen))
|
|
|
|
b.ResetTimer()
|
|
|
|
|
|
|
|
for i := 0; i < b.N; i++ {
|
|
|
|
conn.Write(msg)
|
|
|
|
if err != nil {
|
|
|
|
b.Fatal(err)
|
|
|
|
}
|
|
|
|
_, err = conn.Read(buf)
|
|
|
|
if err != nil {
|
|
|
|
b.Fatal(err)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
<-done
|
|
|
|
}
|