mirror of
https://github.com/fatedier/frp.git
synced 2025-07-27 07:35:07 +00:00
more e2e test cases (#2450)
This commit is contained in:
@@ -14,6 +14,10 @@ func ExpectEqualValues(actual interface{}, extra interface{}, explain ...interfa
|
||||
gomega.ExpectWithOffset(1, actual).To(gomega.BeEquivalentTo(extra), explain...)
|
||||
}
|
||||
|
||||
func ExpectEqualValuesWithOffset(offset int, actual interface{}, extra interface{}, explain ...interface{}) {
|
||||
gomega.ExpectWithOffset(1+offset, actual).To(gomega.BeEquivalentTo(extra), explain...)
|
||||
}
|
||||
|
||||
// ExpectNotEqual expects the specified two are not the same, otherwise an exception raises
|
||||
func ExpectNotEqual(actual interface{}, extra interface{}, explain ...interface{}) {
|
||||
gomega.ExpectWithOffset(1, actual).NotTo(gomega.Equal(extra), explain...)
|
||||
@@ -24,6 +28,10 @@ func ExpectError(err error, explain ...interface{}) {
|
||||
gomega.ExpectWithOffset(1, err).To(gomega.HaveOccurred(), explain...)
|
||||
}
|
||||
|
||||
func ExpectErrorWithOffset(offset int, err error, explain ...interface{}) {
|
||||
gomega.ExpectWithOffset(1+offset, err).To(gomega.HaveOccurred(), explain...)
|
||||
}
|
||||
|
||||
// ExpectNoError checks if "err" is set, and if so, fails assertion while logging the error.
|
||||
func ExpectNoError(err error, explain ...interface{}) {
|
||||
ExpectNoErrorWithOffset(1, err, explain...)
|
||||
@@ -40,6 +48,14 @@ func ExpectConsistOf(actual interface{}, extra interface{}, explain ...interface
|
||||
gomega.ExpectWithOffset(1, actual).To(gomega.ConsistOf(extra), explain...)
|
||||
}
|
||||
|
||||
func ExpectContainElements(actual interface{}, extra interface{}, explain ...interface{}) {
|
||||
gomega.ExpectWithOffset(1, actual).To(gomega.ContainElements(extra), explain...)
|
||||
}
|
||||
|
||||
func ExpectNotContainElements(actual interface{}, extra interface{}, explain ...interface{}) {
|
||||
gomega.ExpectWithOffset(1, actual).NotTo(gomega.ContainElements(extra), explain...)
|
||||
}
|
||||
|
||||
// ExpectHaveKey expects the actual map has the key in the keyset
|
||||
func ExpectHaveKey(actual interface{}, key interface{}, explain ...interface{}) {
|
||||
gomega.ExpectWithOffset(1, actual).To(gomega.HaveKey(key), explain...)
|
||||
@@ -53,3 +69,7 @@ func ExpectEmpty(actual interface{}, explain ...interface{}) {
|
||||
func ExpectTrue(actual interface{}, explain ...interface{}) {
|
||||
gomega.ExpectWithOffset(1, actual).Should(gomega.BeTrue(), explain...)
|
||||
}
|
||||
|
||||
func ExpectTrueWithOffset(offset int, actual interface{}, explain ...interface{}) {
|
||||
gomega.ExpectWithOffset(1+offset, actual).Should(gomega.BeTrue(), explain...)
|
||||
}
|
||||
|
@@ -30,6 +30,9 @@ type Framework struct {
|
||||
// ports used in this framework indexed by port name.
|
||||
usedPorts map[string]int
|
||||
|
||||
// record ports alloced by this framework and release them after each test
|
||||
allocedPorts []int
|
||||
|
||||
// portAllocator to alloc port for this test case.
|
||||
portAllocator *port.Allocator
|
||||
|
||||
@@ -50,7 +53,13 @@ type Framework struct {
|
||||
clientProcesses []*process.Process
|
||||
|
||||
// Manual registered mock servers.
|
||||
servers []*server.Server
|
||||
servers []server.Server
|
||||
|
||||
// used to generate unique config file name.
|
||||
configFileIndex int64
|
||||
|
||||
// envs used to start processes, the form is `key=value`.
|
||||
osEnvs []string
|
||||
}
|
||||
|
||||
func NewDefaultFramework() *Framework {
|
||||
@@ -80,7 +89,7 @@ func (f *Framework) BeforeEach() {
|
||||
|
||||
f.cleanupHandle = AddCleanupAction(f.AfterEach)
|
||||
|
||||
dir, err := ioutil.TempDir(os.TempDir(), "frpe2e-test-*")
|
||||
dir, err := ioutil.TempDir(os.TempDir(), "frp-e2e-test-*")
|
||||
ExpectNoError(err)
|
||||
f.TempDirectory = dir
|
||||
|
||||
@@ -88,6 +97,14 @@ func (f *Framework) BeforeEach() {
|
||||
if err := f.mockServers.Run(); err != nil {
|
||||
Failf("%v", err)
|
||||
}
|
||||
|
||||
params := f.mockServers.GetTemplateParams()
|
||||
for k, v := range params {
|
||||
switch t := v.(type) {
|
||||
case int:
|
||||
f.usedPorts[k] = int(t)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (f *Framework) AfterEach() {
|
||||
@@ -126,14 +143,23 @@ func (f *Framework) AfterEach() {
|
||||
// clean directory
|
||||
os.RemoveAll(f.TempDirectory)
|
||||
f.TempDirectory = ""
|
||||
f.serverConfPaths = nil
|
||||
f.clientConfPaths = nil
|
||||
f.serverConfPaths = []string{}
|
||||
f.clientConfPaths = []string{}
|
||||
|
||||
// release used ports
|
||||
for _, port := range f.usedPorts {
|
||||
f.portAllocator.Release(port)
|
||||
}
|
||||
f.usedPorts = make(map[string]int)
|
||||
|
||||
// release alloced ports
|
||||
for _, port := range f.allocedPorts {
|
||||
f.portAllocator.Release(port)
|
||||
}
|
||||
f.allocedPorts = make([]int, 0)
|
||||
|
||||
// clear os envs
|
||||
f.osEnvs = make([]string, 0)
|
||||
}
|
||||
|
||||
var portRegex = regexp.MustCompile(`{{ \.Port.*? }}`)
|
||||
@@ -210,6 +236,7 @@ func (f *Framework) PortByName(name string) int {
|
||||
func (f *Framework) AllocPort() int {
|
||||
port := f.portAllocator.Get()
|
||||
ExpectTrue(port > 0, "alloc port failed")
|
||||
f.allocedPorts = append(f.allocedPorts, port)
|
||||
return port
|
||||
}
|
||||
|
||||
@@ -217,11 +244,15 @@ func (f *Framework) ReleasePort(port int) {
|
||||
f.portAllocator.Release(port)
|
||||
}
|
||||
|
||||
func (f *Framework) RunServer(portName string, s *server.Server) {
|
||||
func (f *Framework) RunServer(portName string, s server.Server) {
|
||||
f.servers = append(f.servers, s)
|
||||
if s.BindPort() > 0 {
|
||||
if s.BindPort() > 0 && portName != "" {
|
||||
f.usedPorts[portName] = s.BindPort()
|
||||
}
|
||||
err := s.Run()
|
||||
ExpectNoError(err, portName)
|
||||
ExpectNoError(err, "RunServer: with PortName %s", portName)
|
||||
}
|
||||
|
||||
func (f *Framework) SetEnvs(envs []string) {
|
||||
f.osEnvs = envs
|
||||
}
|
||||
|
@@ -2,35 +2,45 @@ package framework
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"net/http"
|
||||
"os"
|
||||
|
||||
"github.com/fatedier/frp/test/e2e/framework/consts"
|
||||
"github.com/fatedier/frp/test/e2e/mock/server"
|
||||
"github.com/fatedier/frp/test/e2e/mock/server/httpserver"
|
||||
"github.com/fatedier/frp/test/e2e/mock/server/streamserver"
|
||||
"github.com/fatedier/frp/test/e2e/pkg/port"
|
||||
)
|
||||
|
||||
const (
|
||||
TCPEchoServerPort = "TCPEchoServerPort"
|
||||
UDPEchoServerPort = "UDPEchoServerPort"
|
||||
UDSEchoServerAddr = "UDSEchoServerAddr"
|
||||
TCPEchoServerPort = "TCPEchoServerPort"
|
||||
UDPEchoServerPort = "UDPEchoServerPort"
|
||||
UDSEchoServerAddr = "UDSEchoServerAddr"
|
||||
HTTPSimpleServerPort = "HTTPSimpleServerPort"
|
||||
)
|
||||
|
||||
type MockServers struct {
|
||||
tcpEchoServer *server.Server
|
||||
udpEchoServer *server.Server
|
||||
udsEchoServer *server.Server
|
||||
tcpEchoServer server.Server
|
||||
udpEchoServer server.Server
|
||||
udsEchoServer server.Server
|
||||
httpSimpleServer server.Server
|
||||
}
|
||||
|
||||
func NewMockServers(portAllocator *port.Allocator) *MockServers {
|
||||
s := &MockServers{}
|
||||
tcpPort := portAllocator.Get()
|
||||
udpPort := portAllocator.Get()
|
||||
s.tcpEchoServer = server.New(server.TCP, server.WithBindPort(tcpPort), server.WithEchoMode(true))
|
||||
s.udpEchoServer = server.New(server.UDP, server.WithBindPort(udpPort), server.WithEchoMode(true))
|
||||
httpPort := portAllocator.Get()
|
||||
s.tcpEchoServer = streamserver.New(streamserver.TCP, streamserver.WithBindPort(tcpPort), streamserver.WithEchoMode(true))
|
||||
s.udpEchoServer = streamserver.New(streamserver.UDP, streamserver.WithBindPort(udpPort), streamserver.WithEchoMode(true))
|
||||
s.httpSimpleServer = httpserver.New(httpserver.WithBindPort(httpPort), httpserver.WithHandler(http.HandlerFunc(func(w http.ResponseWriter, req *http.Request) {
|
||||
w.Write([]byte(consts.TestString))
|
||||
})))
|
||||
|
||||
udsIndex := portAllocator.Get()
|
||||
udsAddr := fmt.Sprintf("%s/frp_echo_server_%d.sock", os.TempDir(), udsIndex)
|
||||
os.Remove(udsAddr)
|
||||
s.udsEchoServer = server.New(server.Unix, server.WithBindAddr(udsAddr), server.WithEchoMode(true))
|
||||
s.udsEchoServer = streamserver.New(streamserver.Unix, streamserver.WithBindAddr(udsAddr), streamserver.WithEchoMode(true))
|
||||
return s
|
||||
}
|
||||
|
||||
@@ -44,6 +54,9 @@ func (m *MockServers) Run() error {
|
||||
if err := m.udsEchoServer.Run(); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := m.httpSimpleServer.Run(); err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -51,6 +64,7 @@ func (m *MockServers) Close() {
|
||||
m.tcpEchoServer.Close()
|
||||
m.udpEchoServer.Close()
|
||||
m.udsEchoServer.Close()
|
||||
m.httpSimpleServer.Close()
|
||||
os.Remove(m.udsEchoServer.BindAddr())
|
||||
}
|
||||
|
||||
@@ -59,6 +73,7 @@ func (m *MockServers) GetTemplateParams() map[string]interface{} {
|
||||
ret[TCPEchoServerPort] = m.tcpEchoServer.BindPort()
|
||||
ret[UDPEchoServerPort] = m.udpEchoServer.BindPort()
|
||||
ret[UDSEchoServerAddr] = m.udsEchoServer.BindAddr()
|
||||
ret[HTTPSimpleServerPort] = m.httpSimpleServer.BindPort()
|
||||
return ret
|
||||
}
|
||||
|
||||
|
@@ -10,10 +10,6 @@ import (
|
||||
"github.com/fatedier/frp/test/e2e/pkg/process"
|
||||
)
|
||||
|
||||
func GenerateConfigFile(path string, content string) error {
|
||||
return ioutil.WriteFile(path, []byte(content), 0666)
|
||||
}
|
||||
|
||||
// RunProcesses run multiple processes from templates.
|
||||
// The first template should always be frps.
|
||||
func (f *Framework) RunProcesses(serverTemplates []string, clientTemplates []string) {
|
||||
@@ -37,7 +33,8 @@ func (f *Framework) RunProcesses(serverTemplates []string, clientTemplates []str
|
||||
err = ioutil.WriteFile(path, []byte(outs[i]), 0666)
|
||||
ExpectNoError(err)
|
||||
flog.Trace("[%s] %s", path, outs[i])
|
||||
p := process.New(TestContext.FRPServerPath, []string{"-c", path})
|
||||
|
||||
p := process.NewWithEnvs(TestContext.FRPServerPath, []string{"-c", path}, f.osEnvs)
|
||||
f.serverConfPaths = append(f.serverConfPaths, path)
|
||||
f.serverProcesses = append(f.serverProcesses, p)
|
||||
err = p.Start()
|
||||
@@ -51,7 +48,8 @@ func (f *Framework) RunProcesses(serverTemplates []string, clientTemplates []str
|
||||
err = ioutil.WriteFile(path, []byte(outs[index]), 0666)
|
||||
ExpectNoError(err)
|
||||
flog.Trace("[%s] %s", path, outs[index])
|
||||
p := process.New(TestContext.FRPClientPath, []string{"-c", path})
|
||||
|
||||
p := process.NewWithEnvs(TestContext.FRPClientPath, []string{"-c", path}, f.osEnvs)
|
||||
f.clientConfPaths = append(f.clientConfPaths, path)
|
||||
f.clientProcesses = append(f.clientProcesses, p)
|
||||
err = p.Start()
|
||||
@@ -60,3 +58,34 @@ func (f *Framework) RunProcesses(serverTemplates []string, clientTemplates []str
|
||||
}
|
||||
time.Sleep(500 * time.Millisecond)
|
||||
}
|
||||
|
||||
func (f *Framework) RunFrps(args ...string) (*process.Process, string, error) {
|
||||
p := process.NewWithEnvs(TestContext.FRPServerPath, args, f.osEnvs)
|
||||
f.serverProcesses = append(f.serverProcesses, p)
|
||||
err := p.Start()
|
||||
if err != nil {
|
||||
return p, p.StdOutput(), err
|
||||
}
|
||||
// sleep for a while to get std output
|
||||
time.Sleep(500 * time.Millisecond)
|
||||
return p, p.StdOutput(), nil
|
||||
}
|
||||
|
||||
func (f *Framework) RunFrpc(args ...string) (*process.Process, string, error) {
|
||||
p := process.NewWithEnvs(TestContext.FRPClientPath, args, f.osEnvs)
|
||||
f.clientProcesses = append(f.clientProcesses, p)
|
||||
err := p.Start()
|
||||
if err != nil {
|
||||
return p, p.StdOutput(), err
|
||||
}
|
||||
time.Sleep(500 * time.Millisecond)
|
||||
return p, p.StdOutput(), nil
|
||||
}
|
||||
|
||||
func (f *Framework) GenerateConfigFile(content string) string {
|
||||
f.configFileIndex++
|
||||
path := filepath.Join(f.TempDirectory, fmt.Sprintf("frp-e2e-config-%d", f.configFileIndex))
|
||||
err := ioutil.WriteFile(path, []byte(content), 0666)
|
||||
ExpectNoError(err)
|
||||
return path
|
||||
}
|
||||
|
@@ -1,38 +1,35 @@
|
||||
package framework
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"net/http"
|
||||
|
||||
flog "github.com/fatedier/frp/pkg/util/log"
|
||||
"github.com/fatedier/frp/test/e2e/framework/consts"
|
||||
"github.com/fatedier/frp/test/e2e/pkg/request"
|
||||
)
|
||||
|
||||
func SetRequestProtocol(protocol string) func(*request.Request) {
|
||||
return func(r *request.Request) {
|
||||
r.Protocol(protocol)
|
||||
func SpecifiedHTTPBodyHandler(body []byte) http.HandlerFunc {
|
||||
return func(w http.ResponseWriter, req *http.Request) {
|
||||
w.Write(body)
|
||||
}
|
||||
}
|
||||
|
||||
func SetRequestPort(port int) func(*request.Request) {
|
||||
return func(r *request.Request) {
|
||||
r.Port(port)
|
||||
func ExpectResponseCode(code int) EnsureFunc {
|
||||
return func(resp *request.Response) bool {
|
||||
return resp.Code == code
|
||||
}
|
||||
}
|
||||
|
||||
// NewRequest return a default TCP request with default timeout and content.
|
||||
// NewRequest return a default request with default timeout and content.
|
||||
func NewRequest() *request.Request {
|
||||
return request.New().
|
||||
Timeout(consts.DefaultTimeout).
|
||||
Body([]byte(consts.TestString))
|
||||
}
|
||||
|
||||
func ExpectResponse(req *request.Request, expectResp []byte, explain ...interface{}) {
|
||||
ret, err := req.Do()
|
||||
ExpectNoError(err, explain...)
|
||||
ExpectEqualValues(expectResp, ret, explain...)
|
||||
}
|
||||
|
||||
func ExpectResponseError(req *request.Request, explain ...interface{}) {
|
||||
_, err := req.Do()
|
||||
ExpectError(err, explain...)
|
||||
func NewHTTPRequest() *request.Request {
|
||||
return request.New().HTTP().HTTPParams("GET", "", "/", nil)
|
||||
}
|
||||
|
||||
type RequestExpect struct {
|
||||
@@ -59,6 +56,11 @@ func (e *RequestExpect) RequestModify(f func(r *request.Request)) *RequestExpect
|
||||
return e
|
||||
}
|
||||
|
||||
func (e *RequestExpect) Protocol(protocol string) *RequestExpect {
|
||||
e.req.Protocol(protocol)
|
||||
return e
|
||||
}
|
||||
|
||||
func (e *RequestExpect) PortName(name string) *RequestExpect {
|
||||
if e.f != nil {
|
||||
e.req.Port(e.f.PortByName(name))
|
||||
@@ -66,6 +68,13 @@ func (e *RequestExpect) PortName(name string) *RequestExpect {
|
||||
return e
|
||||
}
|
||||
|
||||
func (e *RequestExpect) Port(port int) *RequestExpect {
|
||||
if e.f != nil {
|
||||
e.req.Port(port)
|
||||
}
|
||||
return e
|
||||
}
|
||||
|
||||
func (e *RequestExpect) ExpectResp(resp []byte) *RequestExpect {
|
||||
e.expectResp = resp
|
||||
return e
|
||||
@@ -81,10 +90,32 @@ func (e *RequestExpect) Explain(explain ...interface{}) *RequestExpect {
|
||||
return e
|
||||
}
|
||||
|
||||
func (e *RequestExpect) Ensure() {
|
||||
type EnsureFunc func(*request.Response) bool
|
||||
|
||||
func (e *RequestExpect) Ensure(fns ...EnsureFunc) {
|
||||
ret, err := e.req.Do()
|
||||
if e.expectError {
|
||||
ExpectResponseError(e.req, e.explain...)
|
||||
ExpectErrorWithOffset(1, err, e.explain...)
|
||||
return
|
||||
}
|
||||
ExpectNoErrorWithOffset(1, err, e.explain...)
|
||||
|
||||
if len(fns) == 0 {
|
||||
if !bytes.Equal(e.expectResp, ret.Content) {
|
||||
flog.Trace("Response info: %+v", ret)
|
||||
}
|
||||
ExpectEqualValuesWithOffset(1, e.expectResp, ret.Content, e.explain...)
|
||||
} else {
|
||||
ExpectResponse(e.req, e.expectResp, e.explain...)
|
||||
for _, fn := range fns {
|
||||
ok := fn(ret)
|
||||
if !ok {
|
||||
flog.Trace("Response info: %+v", ret)
|
||||
}
|
||||
ExpectTrueWithOffset(1, ok, e.explain...)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (e *RequestExpect) Do() (*request.Response, error) {
|
||||
return e.req.Do()
|
||||
}
|
||||
|
@@ -9,6 +9,5 @@ import (
|
||||
var RunID string
|
||||
|
||||
func init() {
|
||||
uuid, _ := uuid.NewUUID()
|
||||
RunID = uuid.String()
|
||||
RunID = uuid.NewString()
|
||||
}
|
||||
|
Reference in New Issue
Block a user