Cloak/internal/multiplex/switchboard_test.go
2019-10-20 15:21:31 +01:00

196 lines
4.0 KiB
Go

package multiplex
import (
"github.com/cbeuw/Cloak/internal/util"
"math/rand"
"net"
"testing"
"time"
)
func TestSwitchboard_Send(t *testing.T) {
getHole := func() net.Conn {
l, _ := net.Listen("tcp", "127.0.0.1:0")
go func() {
net.Dial("tcp", l.Addr().String())
}()
hole, _ := l.Accept()
return hole
}
doTest := func(seshConfig *SessionConfig) {
sesh := MakeSession(0, seshConfig)
hole0 := getHole()
sesh.sb.addConn(hole0)
connId, err := sesh.sb.assignRandomConn()
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
}
hole1 := getHole()
sesh.sb.addConn(hole1)
connId, err = sesh.sb.assignRandomConn()
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.assignRandomConn()
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) {
seshConfig := &SessionConfig{
Obfuscator: nil,
Valve: nil,
UnitRead: util.ReadTLS,
Unordered: false,
}
doTest(seshConfig)
})
t.Run("Unordered", func(t *testing.T) {
seshConfig := &SessionConfig{
Obfuscator: nil,
Valve: nil,
UnitRead: util.ReadTLS,
Unordered: true,
}
doTest(seshConfig)
})
}
func BenchmarkSwitchboard_Send(b *testing.B) {
hole := newBlackHole()
seshConfig := &SessionConfig{
Obfuscator: nil,
Valve: nil,
UnitRead: util.ReadTLS,
}
sesh := MakeSession(0, seshConfig)
sesh.sb.addConn(hole)
connId, err := sesh.sb.assignRandomConn()
if err != nil {
b.Error("failed to get a random conn", err)
return
}
data := make([]byte, 1000)
rand.Read(data)
b.ResetTimer()
for i := 0; i < b.N; i++ {
n, err := sesh.sb.send(data, &connId)
if err != nil {
b.Error(err)
return
}
b.SetBytes(int64(n))
}
}
func TestSwitchboard_TxCredit(t *testing.T) {
seshConfig := &SessionConfig{
Obfuscator: nil,
Valve: MakeValve(1<<20, 1<<20),
UnitRead: util.ReadTLS,
}
sesh := MakeSession(0, seshConfig)
hole := newBlackHole()
sesh.sb.addConn(hole)
connId, err := sesh.sb.assignRandomConn()
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) {
*sesh.sb.Valve.(*LimitedValve).tx = 0
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
}
if *sesh.sb.Valve.(*LimitedValve).tx != 10 {
t.Error("tx credit didn't increase by 10")
}
})
t.Run("UNIFORM", func(t *testing.T) {
*sesh.sb.Valve.(*LimitedValve).tx = 0
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
}
if *sesh.sb.Valve.(*LimitedValve).tx != 10 {
t.Error("tx credit didn't increase by 10")
}
})
}
func TestSwitchboard_CloseOnOneDisconn(t *testing.T) {
sesh := setupSesh(false)
l, _ := net.Listen("tcp", "127.0.0.1:0")
addRemoteConn := func(close chan struct{}) {
conn, _ := net.Dial("tcp", l.Addr().String())
for {
conn.Write([]byte{0x00})
<-close
conn.Close()
}
}
close0 := make(chan struct{})
go addRemoteConn(close0)
conn0, _ := l.Accept()
sesh.AddConnection(conn0)
close1 := make(chan struct{})
go addRemoteConn(close1)
conn1, _ := l.Accept()
sesh.AddConnection(conn1)
close0 <- struct{}{}
time.Sleep(100 * time.Millisecond)
if !sesh.IsClosed() {
t.Error("session not closed after one conn is disconnected")
return
}
if _, err := conn1.Write([]byte{0x00}); err == nil {
t.Error("the other conn is still connected")
return
}
}