5
0
mirror of https://github.com/cwinfo/yggdrasil-go.git synced 2024-11-29 16:41:36 +00:00
yggdrasil-go/src/core/core_test.go

194 lines
4.4 KiB
Go
Raw Normal View History

2021-05-23 19:42:26 +00:00
package core
2019-09-25 13:58:19 +00:00
import (
2019-09-25 18:07:36 +00:00
"bytes"
"math/rand"
2021-05-29 16:13:59 +00:00
"net/url"
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"
2021-06-28 17:28:56 +00:00
"github.com/yggdrasil-network/yggdrasil-go/src/defaults"
2019-09-25 13:58:19 +00:00
)
// GenerateConfig produces default configuration with suitable modifications for tests.
2019-09-25 13:58:19 +00:00
func GenerateConfig() *config.NodeConfig {
2021-06-28 17:28:56 +00:00
cfg := defaults.GenerateConfig()
2019-09-25 13:58:19 +00:00
cfg.AdminListen = "none"
cfg.Listen = []string{"tcp://127.0.0.1:0"}
cfg.IfName = "none"
return cfg
}
2019-11-29 09:45:02 +00:00
// GetLoggerWithPrefix creates a new logger instance with prefix.
// If verbose is set to true, three log levels are enabled: "info", "warn", "error".
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
}
// CreateAndConnectTwo creates two nodes. nodeB connects to nodeA.
// Verbosity flag is passed to logger.
func CreateAndConnectTwo(t testing.TB, verbose bool) (nodeA *Core, nodeB *Core) {
nodeA = new(Core)
if err := nodeA.Start(GenerateConfig(), GetLoggerWithPrefix("A: ", verbose)); err != nil {
2019-09-25 13:58:19 +00:00
t.Fatal(err)
}
nodeA.SetMTU(1500)
2019-09-25 13:58:19 +00:00
nodeB = new(Core)
if err := nodeB.Start(GenerateConfig(), GetLoggerWithPrefix("B: ", verbose)); err != nil {
2019-09-25 13:58:19 +00:00
t.Fatal(err)
}
nodeB.SetMTU(1500)
2019-09-25 13:58:19 +00:00
2021-05-29 16:13:59 +00:00
u, err := url.Parse("tcp://" + nodeA.links.tcp.getAddr().String())
if err != nil {
t.Fatal(err)
}
err = nodeB.CallPeer(u, "")
2019-09-25 13:58:19 +00:00
if err != nil {
t.Fatal(err)
}
2019-09-25 18:07:36 +00:00
2021-05-29 16:13:59 +00:00
time.Sleep(100 * time.Millisecond)
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-25 18:07:36 +00:00
}
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)
2021-05-29 16:13:59 +00:00
if len(nodeA.GetPeers()) > 0 && len(nodeB.GetPeers()) > 0 {
2019-09-28 12:10:17 +00:00
return true
}
}
return false
}
// CreateEchoListener creates a routine listening on nodeA. It expects repeats messages of length bufLen.
// It returns a channel used to synchronize the routine with caller.
2019-09-28 12:20:57 +00:00
func CreateEchoListener(t testing.TB, nodeA *Core, bufLen int, repeats int) chan struct{} {
// Start routine
2019-09-25 18:07:36 +00:00
done := make(chan struct{})
go func() {
2019-09-28 12:10:17 +00:00
buf := make([]byte, bufLen)
res := make([]byte, bufLen)
2019-09-28 12:20:57 +00:00
for i := 0; i < repeats; i++ {
n, err := nodeA.Read(buf)
2019-09-28 12:20:57 +00:00
if err != nil {
t.Error(err)
return
}
if n != bufLen {
t.Error("missing data")
return
}
copy(res, buf)
copy(res[8:24], buf[24:40])
copy(res[24:40], buf[8:24])
_, err = nodeA.Write(res)
2019-09-28 12:20:57 +00:00
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
}
// TestCore_Start_Connect checks if two nodes can connect together.
func TestCore_Start_Connect(t *testing.T) {
CreateAndConnectTwo(t, true)
}
// TestCore_Start_Transfer checks that messages can be passed between nodes (in both directions).
2019-09-28 12:10:17 +00:00
func TestCore_Start_Transfer(t *testing.T) {
2019-09-28 12:24:54 +00:00
nodeA, nodeB := CreateAndConnectTwo(t, true)
2021-05-29 16:13:59 +00:00
defer nodeA.Stop()
defer nodeB.Stop()
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")
}
2021-05-29 16:13:59 +00:00
// Send
2019-09-28 12:10:17 +00:00
msg := make([]byte, msgLen)
rand.Read(msg[40:])
msg[0] = 0x60
copy(msg[8:24], nodeB.Address())
copy(msg[24:40], nodeA.Address())
_, err := nodeB.Write(msg)
2019-09-25 18:07:36 +00:00
if err != nil {
t.Fatal(err)
}
2019-09-28 12:10:17 +00:00
buf := make([]byte, msgLen)
_, err = nodeB.Read(buf)
2019-09-25 18:07:36 +00:00
if err != nil {
t.Fatal(err)
}
if !bytes.Equal(msg[40:], buf[40:]) {
2019-09-25 18:07:36 +00:00
t.Fatal("expected echo")
}
<-done
2019-09-25 13:58:19 +00:00
}
2019-09-28 12:20:57 +00:00
// BenchmarkCore_Start_Transfer estimates the possible transfer between nodes (in MB/s).
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")
}
2021-05-29 16:13:59 +00:00
// Send
2019-09-28 12:20:57 +00:00
msg := make([]byte, msgLen)
rand.Read(msg[40:])
msg[0] = 0x60
copy(msg[8:24], nodeB.Address())
copy(msg[24:40], nodeA.Address())
2019-09-28 12:20:57 +00:00
buf := make([]byte, msgLen)
b.SetBytes(int64(msgLen))
2019-09-28 12:20:57 +00:00
b.ResetTimer()
for i := 0; i < b.N; i++ {
_, err := nodeB.Write(msg)
2019-09-28 12:20:57 +00:00
if err != nil {
b.Fatal(err)
}
_, err = nodeB.Read(buf)
2019-09-28 12:20:57 +00:00
if err != nil {
b.Fatal(err)
}
}
<-done
}