Skip to content

Commit

Permalink
add e2e tests (fatedier#2334)
Browse files Browse the repository at this point in the history
  • Loading branch information
fatedier authored Mar 31, 2021
1 parent 9a849a2 commit fbaa5f8
Show file tree
Hide file tree
Showing 20 changed files with 541 additions and 166 deletions.
2 changes: 1 addition & 1 deletion client/proxy/proxy_wrapper.go
Original file line number Diff line number Diff line change
Expand Up @@ -227,7 +227,7 @@ func (pw *Wrapper) InWorkConn(workConn net.Conn, m *msg.StartWorkConn) {
pw.mu.RLock()
pxy := pw.pxy
pw.mu.RUnlock()
if pxy != nil {
if pxy != nil && pw.Phase == ProxyPhaseRunning {
xl.Debug("start a new work connection, localAddr: %s remoteAddr: %s", workConn.LocalAddr().String(), workConn.RemoteAddr().String())
go pxy.InWorkConn(workConn, m)
} else {
Expand Down
5 changes: 3 additions & 2 deletions client/visitor.go
Original file line number Diff line number Diff line change
Expand Up @@ -366,7 +366,7 @@ func (sv *SUDPVisitor) Run() (err error) {
sv.sendCh = make(chan *msg.UDPPacket, 1024)
sv.readCh = make(chan *msg.UDPPacket, 1024)

xl.Info("sudp start to work")
xl.Info("sudp start to work, listen on %s", addr)

go sv.dispatcher()
go udp.ForwardUserConn(sv.udpConn, sv.readCh, sv.sendCh, int(sv.ctl.clientCfg.UDPPacketSize))
Expand Down Expand Up @@ -446,7 +446,7 @@ func (sv *SUDPVisitor) worker(workConn net.Conn) {
case *msg.UDPPacket:
if errRet := errors.PanicToError(func() {
sv.readCh <- m
xl.Trace("frpc visitor get udp packet from frpc")
xl.Trace("frpc visitor get udp packet from workConn: %s", m.Content)
}); errRet != nil {
xl.Info("reader goroutine for udp work connection closed")
return
Expand Down Expand Up @@ -475,6 +475,7 @@ func (sv *SUDPVisitor) worker(workConn net.Conn) {
xl.Warn("sender goroutine for udp work connection closed: %v", errRet)
return
}
xl.Trace("send udp package to workConn: %s", udpMsg.Content)
case <-closeCh:
return
}
Expand Down
2 changes: 1 addition & 1 deletion go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ require (
github.com/google/uuid v1.1.1
github.com/gorilla/mux v1.7.3
github.com/gorilla/websocket v1.4.0
github.com/hashicorp/yamux v0.0.0-20181012175058-2f1d1f20f75d
github.com/hashicorp/yamux v0.0.0-20210316155119-a95892c5f864
github.com/inconshreveable/mousetrap v1.0.0 // indirect
github.com/klauspost/cpuid v1.2.0 // indirect
github.com/klauspost/reedsolomon v1.9.1 // indirect
Expand Down
4 changes: 2 additions & 2 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -78,8 +78,8 @@ github.com/gorilla/mux v1.7.3/go.mod h1:1lud6UwP+6orDFRuTfBEV8e9/aOM/c4fVVCaMa2z
github.com/gorilla/websocket v1.4.0 h1:WDFjx/TMzVgy9VdMMQi2K2Emtwi2QcUQsztZ/zLaH/Q=
github.com/gorilla/websocket v1.4.0/go.mod h1:E7qHFY5m1UJ88s3WnNqhKjPHQ0heANvMoAMk2YaljkQ=
github.com/hashicorp/golang-lru v0.5.1/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8=
github.com/hashicorp/yamux v0.0.0-20181012175058-2f1d1f20f75d h1:kJCB4vdITiW1eC1vq2e6IsrXKrZit1bv/TDYFGMp4BQ=
github.com/hashicorp/yamux v0.0.0-20181012175058-2f1d1f20f75d/go.mod h1:+NfK9FKeTrX5uv1uIXGdwYDTeHna2qgaIlx54MXqjAM=
github.com/hashicorp/yamux v0.0.0-20210316155119-a95892c5f864 h1:Y4V+SFe7d3iH+9pJCoeWIOS5/xBJIFsltS7E+KJSsJY=
github.com/hashicorp/yamux v0.0.0-20210316155119-a95892c5f864/go.mod h1:CtWFDAQgb7dxtzFs4tWbplKIe2jSi3+5vKbgIO0SLnQ=
github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU=
github.com/inconshreveable/mousetrap v1.0.0 h1:Z8tu5sraLXCXIcARxBp/8cbvlwVa7Z1NHg9XEKhtSvM=
github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8=
Expand Down
2 changes: 1 addition & 1 deletion server/proxy/udp.go
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,7 @@ func (pxy *UDPProxy) Run() (remoteAddr string, err error) {
xl := pxy.xl
pxy.realPort, err = pxy.rc.UDPPortManager.Acquire(pxy.name, pxy.cfg.RemotePort)
if err != nil {
return
return "", fmt.Errorf("acquire port %d error: %v", pxy.cfg.RemotePort, err)
}
defer func() {
if err != nil {
Expand Down
120 changes: 97 additions & 23 deletions test/e2e/basic/basic.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,16 +3,15 @@ package basic
import (
"fmt"
"strings"
"time"

"github.com/fatedier/frp/test/e2e/framework"
"github.com/fatedier/frp/test/e2e/framework/consts"
"github.com/fatedier/frp/test/e2e/pkg/port"
"github.com/fatedier/frp/test/e2e/pkg/request"

. "github.com/onsi/ginkgo"
)

var connTimeout = 2 * time.Second

var _ = Describe("[Feature: Basic]", func() {
f := framework.NewDefaultFramework()

Expand Down Expand Up @@ -50,21 +49,21 @@ var _ = Describe("[Feature: Basic]", func() {
}{
{
proxyName: "normal",
portName: framework.GenPortName("Normal"),
portName: port.GenName("Normal"),
},
{
proxyName: "with-encryption",
portName: framework.GenPortName("WithEncryption"),
portName: port.GenName("WithEncryption"),
extraConfig: "use_encryption = true",
},
{
proxyName: "with-compression",
portName: framework.GenPortName("WithCompression"),
portName: port.GenName("WithCompression"),
extraConfig: "use_compression = true",
},
{
proxyName: "with-encryption-and-compression",
portName: framework.GenPortName("WithEncryptionAndCompression"),
portName: port.GenName("WithEncryptionAndCompression"),
extraConfig: `
use_encryption = true
use_compression = true
Expand All @@ -80,8 +79,11 @@ var _ = Describe("[Feature: Basic]", func() {
f.RunProcesses([]string{serverConf}, []string{clientConf})

for _, test := range tests {
framework.ExpectRequest(protocol, f.UsedPorts[test.portName],
[]byte(consts.TestString), []byte(consts.TestString), connTimeout, test.proxyName)
framework.NewRequestExpect(f).
Request(framework.SetRequestProtocol(protocol)).
PortName(test.portName).
Explain(test.proxyName).
Ensure()
}
})
}
Expand Down Expand Up @@ -139,24 +141,24 @@ var _ = Describe("[Feature: Basic]", func() {
}{
{
proxyName: "normal",
bindPortName: framework.GenPortName("Normal"),
bindPortName: port.GenName("Normal"),
visitorSK: correctSK,
},
{
proxyName: "with-encryption",
bindPortName: framework.GenPortName("WithEncryption"),
bindPortName: port.GenName("WithEncryption"),
visitorSK: correctSK,
extraConfig: "use_encryption = true",
},
{
proxyName: "with-compression",
bindPortName: framework.GenPortName("WithCompression"),
bindPortName: port.GenName("WithCompression"),
visitorSK: correctSK,
extraConfig: "use_compression = true",
},
{
proxyName: "with-encryption-and-compression",
bindPortName: framework.GenPortName("WithEncryptionAndCompression"),
bindPortName: port.GenName("WithEncryptionAndCompression"),
visitorSK: correctSK,
extraConfig: `
use_encryption = true
Expand All @@ -165,7 +167,7 @@ var _ = Describe("[Feature: Basic]", func() {
},
{
proxyName: "with-error-sk",
bindPortName: framework.GenPortName("WithErrorSK"),
bindPortName: port.GenName("WithErrorSK"),
visitorSK: wrongSK,
expectError: true,
},
Expand All @@ -182,17 +184,89 @@ var _ = Describe("[Feature: Basic]", func() {
f.RunProcesses([]string{serverConf}, []string{clientServerConf, clientVisitorConf})

for _, test := range tests {
expectResp := []byte(consts.TestString)
if test.expectError {
framework.ExpectRequestError(protocol, f.UsedPorts[test.bindPortName],
[]byte(consts.TestString), connTimeout, test.proxyName)
continue
}

framework.ExpectRequest(protocol, f.UsedPorts[test.bindPortName],
[]byte(consts.TestString), expectResp, connTimeout, test.proxyName)
framework.NewRequestExpect(f).
Request(framework.SetRequestProtocol(protocol)).
PortName(test.bindPortName).
Explain(test.proxyName).
ExpectError(test.expectError).
Ensure()

}
})
}
})

Describe("TCPMUX", func() {
It("Type tcpmux", func() {
serverConf := consts.DefaultServerConfig
clientConf := consts.DefaultClientConfig

tcpmuxHTTPConnectPortName := port.GenName("TCPMUX")
serverConf += fmt.Sprintf(`
tcpmux_httpconnect_port = {{ .%s }}
`, tcpmuxHTTPConnectPortName)

getProxyConf := func(proxyName string, extra string) string {
return fmt.Sprintf(`
[%s]
type = tcpmux
multiplexer = httpconnect
local_port = {{ .%s }}
custom_domains = %s
`+extra, proxyName, framework.TCPEchoServerPort, proxyName)
}

tests := []struct {
proxyName string
portName string
extraConfig string
}{
{
proxyName: "normal",
},
{
proxyName: "with-encryption",
extraConfig: "use_encryption = true",
},
{
proxyName: "with-compression",
extraConfig: "use_compression = true",
},
{
proxyName: "with-encryption-and-compression",
extraConfig: `
use_encryption = true
use_compression = true
`,
},
}

// build all client config
for _, test := range tests {
clientConf += getProxyConf(test.proxyName, test.extraConfig) + "\n"
}
// run frps and frpc
f.RunProcesses([]string{serverConf}, []string{clientConf})

// Request without HTTP connect should get error
framework.NewRequestExpect(f).
PortName(tcpmuxHTTPConnectPortName).
ExpectError(true).
Explain("request without HTTP connect expect error").
Ensure()

proxyURL := fmt.Sprintf("http://127.0.0.1:%d", f.PortByName(tcpmuxHTTPConnectPortName))
// Request with incorrect connect hostname
framework.NewRequestExpect(f).Request(func(r *request.Request) {
r.Proxy(proxyURL, "invalid")
}).ExpectError(true).Explain("request without HTTP connect expect error").Ensure()

// Request with correct connect hostname
for _, test := range tests {
framework.NewRequestExpect(f).Request(func(r *request.Request) {
r.Proxy(proxyURL, test.proxyName)
}).Explain(test.proxyName).Ensure()
}
})
})
})
22 changes: 9 additions & 13 deletions test/e2e/basic/client_server.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import (

"github.com/fatedier/frp/test/e2e/framework"
"github.com/fatedier/frp/test/e2e/framework/consts"
"github.com/fatedier/frp/test/e2e/pkg/port"

. "github.com/onsi/ginkgo"
)
Expand All @@ -16,6 +17,7 @@ type generalTestConfigures struct {
expectError bool
}

// defineClientServerTest test a normal tcp and udp proxy with specified TestConfigures.
func defineClientServerTest(desc string, f *framework.Framework, configures *generalTestConfigures) {
It(desc, func() {
serverConf := consts.DefaultServerConfig
Expand All @@ -25,6 +27,8 @@ func defineClientServerTest(desc string, f *framework.Framework, configures *gen
%s
`, configures.server)

tcpPortName := port.GenName("TCP")
udpPortName := port.GenName("UDP")
clientConf += fmt.Sprintf(`
%s
Expand All @@ -38,23 +42,15 @@ func defineClientServerTest(desc string, f *framework.Framework, configures *gen
local_port = {{ .%s }}
remote_port = {{ .%s }}
`, configures.client,
framework.TCPEchoServerPort, framework.GenPortName("TCP"),
framework.UDPEchoServerPort, framework.GenPortName("UDP"),
framework.TCPEchoServerPort, tcpPortName,
framework.UDPEchoServerPort, udpPortName,
)

f.RunProcesses([]string{serverConf}, []string{clientConf})

if !configures.expectError {
framework.ExpectTCPRequest(f.UsedPorts[framework.GenPortName("TCP")],
[]byte(consts.TestString), []byte(consts.TestString), connTimeout, "tcp proxy")
framework.ExpectUDPRequest(f.UsedPorts[framework.GenPortName("UDP")],
[]byte(consts.TestString), []byte(consts.TestString), connTimeout, "udp proxy")
} else {
framework.ExpectTCPRequestError(f.UsedPorts[framework.GenPortName("TCP")],
[]byte(consts.TestString), connTimeout, "tcp proxy")
framework.ExpectUDPRequestError(f.UsedPorts[framework.GenPortName("UDP")],
[]byte(consts.TestString), connTimeout, "udp proxy")
}
framework.NewRequestExpect(f).PortName(tcpPortName).ExpectError(configures.expectError).Explain("tcp proxy").Ensure()
framework.NewRequestExpect(f).Request(framework.SetRequestProtocol("udp")).
PortName(udpPortName).ExpectError(configures.expectError).Explain("udp proxy").Ensure()
})
}

Expand Down
79 changes: 79 additions & 0 deletions test/e2e/basic/server.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
package basic

import (
"fmt"

"github.com/fatedier/frp/test/e2e/framework"
"github.com/fatedier/frp/test/e2e/framework/consts"
"github.com/fatedier/frp/test/e2e/pkg/port"
"github.com/fatedier/frp/test/e2e/pkg/request"

. "github.com/onsi/ginkgo"
)

var _ = Describe("[Feature: Server Manager]", func() {
f := framework.NewDefaultFramework()

It("Ports Whitelist", func() {
serverConf := consts.DefaultServerConfig
clientConf := consts.DefaultClientConfig

serverConf += `
allow_ports = 10000-20000,20002,30000-50000
`

tcpPortName := port.GenName("TCP", port.WithRangePorts(10000, 20000))
udpPortName := port.GenName("UDP", port.WithRangePorts(30000, 50000))
clientConf += fmt.Sprintf(`
[tcp-allowded-in-range]
type = tcp
local_port = {{ .%s }}
remote_port = {{ .%s }}
`, framework.TCPEchoServerPort, tcpPortName)
clientConf += fmt.Sprintf(`
[tcp-port-not-allowed]
type = tcp
local_port = {{ .%s }}
remote_port = 20001
`, framework.TCPEchoServerPort)
clientConf += fmt.Sprintf(`
[tcp-port-unavailable]
type = tcp
local_port = {{ .%s }}
remote_port = {{ .%s }}
`, framework.TCPEchoServerPort, consts.PortServerName)
clientConf += fmt.Sprintf(`
[udp-allowed-in-range]
type = udp
local_port = {{ .%s }}
remote_port = {{ .%s }}
`, framework.UDPEchoServerPort, udpPortName)
clientConf += fmt.Sprintf(`
[udp-port-not-allowed]
type = udp
local_port = {{ .%s }}
remote_port = 20003
`, framework.UDPEchoServerPort)

f.RunProcesses([]string{serverConf}, []string{clientConf})

// TCP
// Allowed in range
framework.NewRequestExpect(f).PortName(tcpPortName).Ensure()

// Not Allowed
framework.NewRequestExpect(f).Request(framework.SetRequestPort(20001)).ExpectError(true).Ensure()

// Unavailable, already bind by frps
framework.NewRequestExpect(f).PortName(consts.PortServerName).ExpectError(true).Ensure()

// UDP
// Allowed in range
framework.NewRequestExpect(f).Request(framework.SetRequestProtocol("udp")).PortName(udpPortName).Ensure()

// Not Allowed
framework.NewRequestExpect(f).Request(func(r *request.Request) {
r.UDP().Port(20003)
}).ExpectError(true).Ensure()
})
})
Loading

0 comments on commit fbaa5f8

Please sign in to comment.