412 lines
7.6 KiB
Go
412 lines
7.6 KiB
Go
|
package tunnel_test
|
||
|
|
||
|
import (
|
||
|
"fmt"
|
||
|
"strconv"
|
||
|
"sync"
|
||
|
"testing"
|
||
|
"time"
|
||
|
|
||
|
"git.xeserv.us/xena/route/lib/tunnel"
|
||
|
"git.xeserv.us/xena/route/lib/tunnel/tunneltest"
|
||
|
"github.com/cenkalti/backoff"
|
||
|
)
|
||
|
|
||
|
func TestMultipleRequest(t *testing.T) {
|
||
|
tt, err := tunneltest.Serve(singleHTTP(handlerEchoHTTP))
|
||
|
if err != nil {
|
||
|
t.Fatal(err)
|
||
|
}
|
||
|
defer tt.Close()
|
||
|
|
||
|
// make a request to tunnelserver, this should be tunneled to local server
|
||
|
var wg sync.WaitGroup
|
||
|
for i := 0; i < 100; i++ {
|
||
|
wg.Add(1)
|
||
|
|
||
|
go func(i int) {
|
||
|
defer wg.Done()
|
||
|
msg := "hello" + strconv.Itoa(i)
|
||
|
res, err := echoHTTP(tt, msg)
|
||
|
if err != nil {
|
||
|
t.Fatalf("echoHTTP error: %s", err)
|
||
|
}
|
||
|
|
||
|
if res != msg {
|
||
|
t.Errorf("got %q, want %q", res, msg)
|
||
|
}
|
||
|
}(i)
|
||
|
}
|
||
|
|
||
|
wg.Wait()
|
||
|
}
|
||
|
|
||
|
func TestMultipleLatencyRequest(t *testing.T) {
|
||
|
tt, err := tunneltest.Serve(singleHTTP(handlerLatencyEchoHTTP))
|
||
|
if err != nil {
|
||
|
t.Fatal(err)
|
||
|
}
|
||
|
defer tt.Close()
|
||
|
|
||
|
// make a request to tunnelserver, this should be tunneled to local server
|
||
|
var wg sync.WaitGroup
|
||
|
for i := 0; i < 100; i++ {
|
||
|
wg.Add(1)
|
||
|
|
||
|
go func(i int) {
|
||
|
defer wg.Done()
|
||
|
msg := "hello" + strconv.Itoa(i)
|
||
|
res, err := echoHTTP(tt, msg)
|
||
|
if err != nil {
|
||
|
t.Fatalf("echoHTTP error: %s", err)
|
||
|
}
|
||
|
|
||
|
if res != msg {
|
||
|
t.Errorf("got %q, want %q", res, msg)
|
||
|
}
|
||
|
}(i)
|
||
|
}
|
||
|
|
||
|
wg.Wait()
|
||
|
}
|
||
|
|
||
|
func TestReconnectClient(t *testing.T) {
|
||
|
tt, err := tunneltest.Serve(singleHTTP(handlerEchoHTTP))
|
||
|
if err != nil {
|
||
|
t.Fatal(err)
|
||
|
}
|
||
|
defer tt.Close()
|
||
|
|
||
|
msg := "hello"
|
||
|
res, err := echoHTTP(tt, msg)
|
||
|
if err != nil {
|
||
|
t.Fatalf("echoHTTP error: %s", err)
|
||
|
}
|
||
|
|
||
|
if res != msg {
|
||
|
t.Errorf("got %q, want %q", res, msg)
|
||
|
}
|
||
|
|
||
|
client := tt.Clients["http"]
|
||
|
|
||
|
// close client, and start it again
|
||
|
client.Close()
|
||
|
|
||
|
go client.Start()
|
||
|
<-client.StartNotify()
|
||
|
|
||
|
msg = "helloagain"
|
||
|
res, err = echoHTTP(tt, msg)
|
||
|
if err != nil {
|
||
|
t.Fatalf("echoHTTP error: %s", err)
|
||
|
}
|
||
|
|
||
|
if res != msg {
|
||
|
t.Errorf("got %q, want %q", res, msg)
|
||
|
}
|
||
|
}
|
||
|
|
||
|
func TestNoClient(t *testing.T) {
|
||
|
const expectedErr = "no client session established"
|
||
|
|
||
|
rec := tunneltest.NewStateRecorder()
|
||
|
|
||
|
tt, err := tunneltest.Serve(singleRecHTTP(handlerEchoHTTP, rec.C()))
|
||
|
if err != nil {
|
||
|
t.Fatal(err)
|
||
|
}
|
||
|
defer tt.Close()
|
||
|
|
||
|
if err := rec.WaitTransitions(
|
||
|
tunnel.ClientStarted,
|
||
|
tunnel.ClientConnecting,
|
||
|
tunnel.ClientConnected,
|
||
|
); err != nil {
|
||
|
t.Fatal(err)
|
||
|
}
|
||
|
|
||
|
if err := tt.ServerStateRecorder.WaitTransition(
|
||
|
tunnel.ClientUnknown,
|
||
|
tunnel.ClientConnected,
|
||
|
); err != nil {
|
||
|
t.Fatal(err)
|
||
|
}
|
||
|
|
||
|
// close client, this is the main point of the test
|
||
|
if err := tt.Clients["http"].Close(); err != nil {
|
||
|
t.Fatal(err)
|
||
|
}
|
||
|
|
||
|
if err := rec.WaitTransitions(
|
||
|
tunnel.ClientConnected,
|
||
|
tunnel.ClientDisconnected,
|
||
|
tunnel.ClientClosed,
|
||
|
); err != nil {
|
||
|
t.Fatal(err)
|
||
|
}
|
||
|
|
||
|
if err := tt.ServerStateRecorder.WaitTransition(
|
||
|
tunnel.ClientConnected,
|
||
|
tunnel.ClientClosed,
|
||
|
); err != nil {
|
||
|
t.Fatal(err)
|
||
|
}
|
||
|
|
||
|
msg := "hello"
|
||
|
res, err := echoHTTP(tt, msg)
|
||
|
if err != nil {
|
||
|
t.Fatalf("echoHTTP error: %s", err)
|
||
|
}
|
||
|
|
||
|
if res != expectedErr {
|
||
|
t.Errorf("got %q, want %q", res, msg)
|
||
|
}
|
||
|
}
|
||
|
|
||
|
func TestNoHost(t *testing.T) {
|
||
|
tt, err := tunneltest.Serve(singleHTTP(handlerEchoHTTP))
|
||
|
if err != nil {
|
||
|
t.Fatal(err)
|
||
|
}
|
||
|
defer tt.Close()
|
||
|
|
||
|
noBackoff := backoff.NewConstantBackOff(time.Duration(-1))
|
||
|
|
||
|
unknown, err := tunnel.NewClient(&tunnel.ClientConfig{
|
||
|
Identifier: "unknown",
|
||
|
ServerAddr: tt.ServerAddr().String(),
|
||
|
Backoff: noBackoff,
|
||
|
Debug: testing.Verbose(),
|
||
|
})
|
||
|
if err != nil {
|
||
|
t.Fatalf("client error: %s", err)
|
||
|
}
|
||
|
unknown.Start()
|
||
|
defer unknown.Close()
|
||
|
|
||
|
if err := tt.ServerStateRecorder.WaitTransition(
|
||
|
tunnel.ClientUnknown,
|
||
|
tunnel.ClientClosed,
|
||
|
); err != nil {
|
||
|
t.Fatal(err)
|
||
|
}
|
||
|
|
||
|
unknown.Start()
|
||
|
if err := tt.ServerStateRecorder.WaitTransition(
|
||
|
tunnel.ClientClosed,
|
||
|
tunnel.ClientClosed,
|
||
|
); err != nil {
|
||
|
t.Fatal(err)
|
||
|
}
|
||
|
}
|
||
|
|
||
|
func TestNoLocalServer(t *testing.T) {
|
||
|
const expectedErr = "no local server"
|
||
|
|
||
|
tt, err := tunneltest.Serve(singleHTTP(handlerEchoHTTP))
|
||
|
if err != nil {
|
||
|
t.Fatal(err)
|
||
|
}
|
||
|
defer tt.Close()
|
||
|
|
||
|
// close local listener, this is the main point of the test
|
||
|
tt.Listeners["http"][0].Close()
|
||
|
|
||
|
msg := "hello"
|
||
|
res, err := echoHTTP(tt, msg)
|
||
|
if err != nil {
|
||
|
t.Fatalf("echoHTTP error: %s", err)
|
||
|
}
|
||
|
|
||
|
if res != expectedErr {
|
||
|
t.Errorf("got %q, want %q", res, msg)
|
||
|
}
|
||
|
}
|
||
|
|
||
|
func TestSingleRequest(t *testing.T) {
|
||
|
tt, err := tunneltest.Serve(singleHTTP(handlerEchoHTTP))
|
||
|
if err != nil {
|
||
|
t.Fatal(err)
|
||
|
}
|
||
|
defer tt.Close()
|
||
|
|
||
|
msg := "hello"
|
||
|
res, err := echoHTTP(tt, msg)
|
||
|
if err != nil {
|
||
|
t.Fatalf("echoHTTP error: %s", err)
|
||
|
}
|
||
|
|
||
|
if res != msg {
|
||
|
t.Errorf("got %q, want %q", res, msg)
|
||
|
}
|
||
|
}
|
||
|
|
||
|
func TestSingleLatencyRequest(t *testing.T) {
|
||
|
tt, err := tunneltest.Serve(singleHTTP(handlerLatencyEchoHTTP))
|
||
|
if err != nil {
|
||
|
t.Fatal(err)
|
||
|
}
|
||
|
defer tt.Close()
|
||
|
|
||
|
msg := "hello"
|
||
|
res, err := echoHTTP(tt, msg)
|
||
|
if err != nil {
|
||
|
t.Fatalf("echoHTTP error: %s", err)
|
||
|
}
|
||
|
|
||
|
if res != msg {
|
||
|
t.Errorf("got %q, want %q", res, msg)
|
||
|
}
|
||
|
}
|
||
|
|
||
|
func TestSingleTCP(t *testing.T) {
|
||
|
tt, err := tunneltest.Serve(singleTCP(handlerEchoTCP))
|
||
|
if err != nil {
|
||
|
t.Fatal(err)
|
||
|
}
|
||
|
defer tt.Close()
|
||
|
|
||
|
msg := "hello"
|
||
|
res, err := echoTCP(tt, msg)
|
||
|
if err != nil {
|
||
|
t.Fatalf("echoTCP error: %s", err)
|
||
|
}
|
||
|
|
||
|
if msg != res {
|
||
|
t.Errorf("got %q, want %q", res, msg)
|
||
|
}
|
||
|
}
|
||
|
|
||
|
func TestMultipleTCP(t *testing.T) {
|
||
|
tt, err := tunneltest.Serve(singleTCP(handlerEchoTCP))
|
||
|
if err != nil {
|
||
|
t.Fatal(err)
|
||
|
}
|
||
|
defer tt.Close()
|
||
|
|
||
|
var wg sync.WaitGroup
|
||
|
for i := 0; i < 100; i++ {
|
||
|
wg.Add(1)
|
||
|
|
||
|
go func(i int) {
|
||
|
defer wg.Done()
|
||
|
msg := "hello" + strconv.Itoa(i)
|
||
|
res, err := echoTCP(tt, msg)
|
||
|
if err != nil {
|
||
|
t.Errorf("echoTCP: %s", err)
|
||
|
}
|
||
|
|
||
|
if res != msg {
|
||
|
t.Errorf("got %q, want %q", res, msg)
|
||
|
}
|
||
|
}(i)
|
||
|
}
|
||
|
|
||
|
wg.Wait()
|
||
|
}
|
||
|
|
||
|
func TestMultipleLatencyTCP(t *testing.T) {
|
||
|
tt, err := tunneltest.Serve(singleTCP(handlerLatencyEchoTCP))
|
||
|
if err != nil {
|
||
|
t.Fatal(err)
|
||
|
}
|
||
|
defer tt.Close()
|
||
|
|
||
|
var wg sync.WaitGroup
|
||
|
for i := 0; i < 100; i++ {
|
||
|
wg.Add(1)
|
||
|
|
||
|
go func(i int) {
|
||
|
defer wg.Done()
|
||
|
msg := "hello" + strconv.Itoa(i)
|
||
|
res, err := echoTCP(tt, msg)
|
||
|
if err != nil {
|
||
|
t.Errorf("echoTCP: %s", err)
|
||
|
}
|
||
|
|
||
|
if res != msg {
|
||
|
t.Errorf("got %q, want %q", res, msg)
|
||
|
}
|
||
|
}(i)
|
||
|
}
|
||
|
|
||
|
wg.Wait()
|
||
|
}
|
||
|
|
||
|
func TestMultipleStreamTCP(t *testing.T) {
|
||
|
tunnels := map[string]*tunneltest.Tunnel{
|
||
|
"http": {
|
||
|
Type: tunneltest.TypeHTTP,
|
||
|
LocalAddr: "127.0.0.1:0",
|
||
|
Handler: handlerEchoHTTP,
|
||
|
},
|
||
|
"tcp": {
|
||
|
Type: tunneltest.TypeTCP,
|
||
|
ClientIdent: "http",
|
||
|
LocalAddr: "127.0.0.1:0",
|
||
|
RemoteAddr: "127.0.0.1:0",
|
||
|
Handler: handlerEchoTCP,
|
||
|
},
|
||
|
"tcp_all": {
|
||
|
Type: tunneltest.TypeTCP,
|
||
|
ClientIdent: "http",
|
||
|
LocalAddr: "127.0.0.1:0",
|
||
|
RemoteAddr: "0.0.0.0:0",
|
||
|
Handler: handlerEchoTCP,
|
||
|
},
|
||
|
}
|
||
|
|
||
|
addrs, err := tunneltest.UsableAddrs()
|
||
|
if err != nil {
|
||
|
t.Fatal(err)
|
||
|
}
|
||
|
|
||
|
clients := []string{"tcp"}
|
||
|
for i, addr := range addrs {
|
||
|
if addr.IP.IsLoopback() {
|
||
|
continue
|
||
|
}
|
||
|
|
||
|
client := fmt.Sprintf("tcp_%d", i)
|
||
|
|
||
|
tunnels[client] = &tunneltest.Tunnel{
|
||
|
Type: tunneltest.TypeTCP,
|
||
|
ClientIdent: "http",
|
||
|
LocalAddr: "127.0.0.1:0",
|
||
|
RemoteAddrIdent: "tcp_all",
|
||
|
IP: addr.IP,
|
||
|
Handler: handlerEchoTCP,
|
||
|
}
|
||
|
|
||
|
clients = append(clients, client)
|
||
|
}
|
||
|
|
||
|
tt, err := tunneltest.Serve(tunnels)
|
||
|
if err != nil {
|
||
|
t.Fatal(err)
|
||
|
}
|
||
|
defer tt.Close()
|
||
|
|
||
|
var wg sync.WaitGroup
|
||
|
for i := 0; i < 100/len(clients); i++ {
|
||
|
wg.Add(len(clients))
|
||
|
|
||
|
for j, ident := range clients {
|
||
|
go func(ident string, i, j int) {
|
||
|
defer wg.Done()
|
||
|
msg := fmt.Sprintf("hello_%d_client_%d", j, i)
|
||
|
res, err := echoTCPIdent(tt, msg, ident)
|
||
|
if err != nil {
|
||
|
t.Errorf("echoTCP: %s", err)
|
||
|
}
|
||
|
|
||
|
if res != msg {
|
||
|
t.Errorf("got %q, want %q", res, msg)
|
||
|
}
|
||
|
}(ident, i, j)
|
||
|
}
|
||
|
}
|
||
|
|
||
|
wg.Wait()
|
||
|
}
|