Cloak/internal/multiplex/switchboard_test.go

186 lines
4.0 KiB
Go
Raw Normal View History

2019-08-08 14:08:16 +00:00
package multiplex
import (
"github.com/cbeuw/connutil"
"github.com/stretchr/testify/assert"
2019-08-08 14:08:16 +00:00
"math/rand"
2020-04-17 00:04:26 +00:00
"sync"
2019-08-08 14:08:16 +00:00
"testing"
2019-10-16 22:00:11 +00:00
"time"
2019-08-08 14:08:16 +00:00
)
2019-09-22 09:44:16 +00:00
func TestSwitchboard_Send(t *testing.T) {
2020-04-08 14:17:33 +00:00
doTest := func(seshConfig SessionConfig) {
2019-09-22 09:44:16 +00:00
sesh := MakeSession(0, seshConfig)
2020-04-08 15:41:39 +00:00
hole0 := connutil.Discard()
2019-09-22 09:44:16 +00:00
sesh.sb.addConn(hole0)
connId, _, err := sesh.sb.pickRandConn()
2019-09-22 09:44:16 +00:00
if err != nil {
t.Error("failed to get a random conn", err)
return
}
data := make([]byte, 1000)
rand.Read(data)
_, err = sesh.sb.send(data, &connId)
if err != nil {
t.Error(err)
return
}
2020-04-08 15:41:39 +00:00
hole1 := connutil.Discard()
2019-09-22 09:44:16 +00:00
sesh.sb.addConn(hole1)
connId, _, err = sesh.sb.pickRandConn()
2019-09-22 09:44:16 +00:00
if err != nil {
t.Error("failed to get a random conn", err)
return
}
_, err = sesh.sb.send(data, &connId)
if err != nil {
t.Error(err)
return
}
connId, _, err = sesh.sb.pickRandConn()
2019-09-22 09:44:16 +00:00
if err != nil {
t.Error("failed to get a random conn", err)
return
}
_, err = sesh.sb.send(data, &connId)
if err != nil {
t.Error(err)
return
}
}
t.Run("Ordered", func(t *testing.T) {
2020-04-08 14:17:33 +00:00
seshConfig := SessionConfig{
2020-04-10 15:14:32 +00:00
Unordered: false,
2019-09-22 09:44:16 +00:00
}
doTest(seshConfig)
})
t.Run("Unordered", func(t *testing.T) {
2020-04-08 14:17:33 +00:00
seshConfig := SessionConfig{
2020-04-10 15:14:32 +00:00
Unordered: true,
2019-09-22 09:44:16 +00:00
}
doTest(seshConfig)
})
}
2019-08-08 14:08:16 +00:00
func BenchmarkSwitchboard_Send(b *testing.B) {
hole := connutil.Discard()
2020-04-10 15:14:32 +00:00
seshConfig := SessionConfig{}
2019-08-11 23:22:15 +00:00
sesh := MakeSession(0, seshConfig)
2019-08-14 09:44:50 +00:00
sesh.sb.addConn(hole)
connId, _, err := sesh.sb.pickRandConn()
2019-08-08 14:08:16 +00:00
if err != nil {
b.Error("failed to get a random conn", err)
return
}
data := make([]byte, 1000)
rand.Read(data)
2020-04-13 18:40:23 +00:00
b.SetBytes(int64(len(data)))
2019-08-08 14:08:16 +00:00
b.ResetTimer()
for i := 0; i < b.N; i++ {
2020-04-13 18:40:23 +00:00
sesh.sb.send(data, &connId)
2019-08-08 14:08:16 +00:00
}
}
2019-08-14 09:44:50 +00:00
func TestSwitchboard_TxCredit(t *testing.T) {
2020-04-08 14:17:33 +00:00
seshConfig := SessionConfig{
2020-04-10 15:14:32 +00:00
Valve: MakeValve(1<<20, 1<<20),
2019-08-14 09:44:50 +00:00
}
sesh := MakeSession(0, seshConfig)
hole := connutil.Discard()
2019-08-14 09:44:50 +00:00
sesh.sb.addConn(hole)
connId, _, err := sesh.sb.pickRandConn()
2019-08-14 09:44:50 +00:00
if err != nil {
t.Error("failed to get a random conn", err)
return
}
data := make([]byte, 1000)
rand.Read(data)
t.Run("FIXED CONN MAPPING", func(t *testing.T) {
2020-04-08 14:17:33 +00:00
*sesh.sb.valve.(*LimitedValve).tx = 0
2019-08-14 09:44:50 +00:00
sesh.sb.strategy = FIXED_CONN_MAPPING
n, err := sesh.sb.send(data[:10], &connId)
if err != nil {
t.Error(err)
return
}
if n != 10 {
t.Errorf("wanted to send %v, got %v", 10, n)
return
}
2020-04-08 14:17:33 +00:00
if *sesh.sb.valve.(*LimitedValve).tx != 10 {
2019-08-14 09:44:50 +00:00
t.Error("tx credit didn't increase by 10")
}
})
t.Run("UNIFORM", func(t *testing.T) {
2020-04-08 14:17:33 +00:00
*sesh.sb.valve.(*LimitedValve).tx = 0
2019-08-14 09:44:50 +00:00
sesh.sb.strategy = UNIFORM_SPREAD
n, err := sesh.sb.send(data[:10], &connId)
if err != nil {
t.Error(err)
return
}
if n != 10 {
t.Errorf("wanted to send %v, got %v", 10, n)
return
}
2020-04-08 14:17:33 +00:00
if *sesh.sb.valve.(*LimitedValve).tx != 10 {
2019-08-14 09:44:50 +00:00
t.Error("tx credit didn't increase by 10")
}
})
}
2019-10-16 22:00:11 +00:00
func TestSwitchboard_CloseOnOneDisconn(t *testing.T) {
2020-04-13 14:17:19 +00:00
var sessionKey [32]byte
rand.Read(sessionKey[:])
2020-10-21 15:42:24 +00:00
sesh := setupSesh(false, sessionKey, EncryptionMethodPlain)
2019-10-16 22:00:11 +00:00
2020-04-08 15:41:39 +00:00
conn0client, conn0server := connutil.AsyncPipe()
sesh.AddConnection(conn0client)
2019-10-16 22:00:11 +00:00
2020-04-08 15:41:39 +00:00
conn1client, _ := connutil.AsyncPipe()
sesh.AddConnection(conn1client)
2019-10-16 22:00:11 +00:00
2020-04-08 15:41:39 +00:00
conn0server.Close()
assert.Eventually(t, func() bool {
return sesh.IsClosed()
}, time.Second, 10*time.Millisecond, "session not closed after one conn is disconnected")
2020-04-08 15:41:39 +00:00
if _, err := conn1client.Write([]byte{0x00}); err == nil {
2019-10-16 22:00:11 +00:00
t.Error("the other conn is still connected")
return
}
}
2020-04-17 00:04:26 +00:00
func TestSwitchboard_ConnsCount(t *testing.T) {
seshConfig := SessionConfig{
Valve: MakeValve(1<<20, 1<<20),
}
sesh := MakeSession(0, seshConfig)
var wg sync.WaitGroup
for i := 0; i < 1000; i++ {
wg.Add(1)
go func() {
sesh.AddConnection(connutil.Discard())
wg.Done()
}()
}
wg.Wait()
if sesh.sb.connsCount() != 1000 {
t.Error("connsCount incorrect")
}
sesh.sb.closeAll()
assert.Eventuallyf(t, func() bool {
return sesh.sb.connsCount() == 0
}, time.Second, 10*time.Millisecond, "connsCount incorrect: %v", sesh.sb.connsCount())
2020-04-17 00:04:26 +00:00
}