test/e2e: optimize e2e test time by replacing sleeps with TCP readiness checks (#5223)

Replace the fixed 500ms sleep after each frps startup in RunProcesses
with a TCP dial-based readiness check that polls the server bind port.
This reduces the e2e suite wall time from ~97s to ~43s.

Also simplify the RunProcesses API to accept a single server template
string instead of a slice, matching how every call site uses it.
This commit is contained in:
fatedier
2026-03-08 23:41:33 +08:00
committed by GitHub
parent c7ac12ea0f
commit bcd2424c24
37 changed files with 224 additions and 191 deletions

View File

@@ -26,7 +26,7 @@ var _ = ginkgo.Describe("[Feature: Example]", func() {
remotePort = %d
`, framework.TCPEchoServerPort, remotePort)
f.RunProcesses([]string{serverConf}, []string{clientConf})
f.RunProcesses(serverConf, []string{clientConf})
framework.NewRequestExpect(f).Port(remotePort).Ensure()
})

View File

@@ -3,67 +3,70 @@ package framework
import (
"fmt"
"maps"
"net"
"os"
"path/filepath"
"slices"
"strconv"
"time"
flog "github.com/fatedier/frp/pkg/util/log"
"github.com/fatedier/frp/test/e2e/framework/consts"
"github.com/fatedier/frp/test/e2e/pkg/process"
)
// RunProcesses run multiple processes from templates.
// The first template should always be frps.
func (f *Framework) RunProcesses(serverTemplates []string, clientTemplates []string) ([]*process.Process, []*process.Process) {
templates := slices.Concat(serverTemplates, clientTemplates)
// RunProcesses starts one frps and zero or more frpc processes from templates.
func (f *Framework) RunProcesses(serverTemplate string, clientTemplates []string) (*process.Process, []*process.Process) {
templates := append([]string{serverTemplate}, clientTemplates...)
outs, ports, err := f.RenderTemplates(templates)
ExpectNoError(err)
ExpectTrue(len(templates) > 0)
maps.Copy(f.usedPorts, ports)
currentServerProcesses := make([]*process.Process, 0, len(serverTemplates))
for i := range serverTemplates {
path := filepath.Join(f.TempDirectory, fmt.Sprintf("frp-e2e-server-%d", i))
err = os.WriteFile(path, []byte(outs[i]), 0o600)
ExpectNoError(err)
// Start frps.
serverPath := filepath.Join(f.TempDirectory, "frp-e2e-server-0")
err = os.WriteFile(serverPath, []byte(outs[0]), 0o600)
ExpectNoError(err)
if TestContext.Debug {
flog.Debugf("[%s] %s", path, outs[i])
}
p := process.NewWithEnvs(TestContext.FRPServerPath, []string{"-c", path}, f.osEnvs)
f.serverConfPaths = append(f.serverConfPaths, path)
f.serverProcesses = append(f.serverProcesses, p)
currentServerProcesses = append(currentServerProcesses, p)
err = p.Start()
ExpectNoError(err)
time.Sleep(500 * time.Millisecond)
if TestContext.Debug {
flog.Debugf("[%s] %s", serverPath, outs[0])
}
time.Sleep(2 * time.Second)
currentClientProcesses := make([]*process.Process, 0, len(clientTemplates))
serverProcess := process.NewWithEnvs(TestContext.FRPServerPath, []string{"-c", serverPath}, f.osEnvs)
f.serverConfPaths = append(f.serverConfPaths, serverPath)
f.serverProcesses = append(f.serverProcesses, serverProcess)
err = serverProcess.Start()
ExpectNoError(err)
if port, ok := ports[consts.PortServerName]; ok {
ExpectNoError(WaitForTCPReady(net.JoinHostPort("127.0.0.1", strconv.Itoa(port)), 5*time.Second))
} else {
time.Sleep(2 * time.Second)
}
// Start frpc(s).
clientProcesses := make([]*process.Process, 0, len(clientTemplates))
for i := range clientTemplates {
index := i + len(serverTemplates)
path := filepath.Join(f.TempDirectory, fmt.Sprintf("frp-e2e-client-%d", i))
err = os.WriteFile(path, []byte(outs[index]), 0o600)
err = os.WriteFile(path, []byte(outs[1+i]), 0o600)
ExpectNoError(err)
if TestContext.Debug {
flog.Debugf("[%s] %s", path, outs[index])
flog.Debugf("[%s] %s", path, outs[1+i])
}
p := process.NewWithEnvs(TestContext.FRPClientPath, []string{"-c", path}, f.osEnvs)
f.clientConfPaths = append(f.clientConfPaths, path)
f.clientProcesses = append(f.clientProcesses, p)
currentClientProcesses = append(currentClientProcesses, p)
clientProcesses = append(clientProcesses, p)
err = p.Start()
ExpectNoError(err)
time.Sleep(500 * time.Millisecond)
}
time.Sleep(3 * time.Second)
// frpc needs time to connect and register proxies with frps.
if len(clientProcesses) > 0 {
time.Sleep(1500 * time.Millisecond)
}
return currentServerProcesses, currentClientProcesses
return serverProcess, clientProcesses
}
func (f *Framework) RunFrps(args ...string) (*process.Process, string, error) {
@@ -71,11 +74,10 @@ func (f *Framework) RunFrps(args ...string) (*process.Process, string, error) {
f.serverProcesses = append(f.serverProcesses, p)
err := p.Start()
if err != nil {
return p, p.StdOutput(), err
return p, p.Output(), err
}
// Give frps extra time to finish binding ports before proceeding.
time.Sleep(4 * time.Second)
return p, p.StdOutput(), nil
time.Sleep(2 * time.Second)
return p, p.Output(), nil
}
func (f *Framework) RunFrpc(args ...string) (*process.Process, string, error) {
@@ -83,10 +85,10 @@ func (f *Framework) RunFrpc(args ...string) (*process.Process, string, error) {
f.clientProcesses = append(f.clientProcesses, p)
err := p.Start()
if err != nil {
return p, p.StdOutput(), err
return p, p.Output(), err
}
time.Sleep(2 * time.Second)
return p, p.StdOutput(), nil
time.Sleep(1500 * time.Millisecond)
return p, p.Output(), nil
}
func (f *Framework) GenerateConfigFile(content string) string {
@@ -96,3 +98,25 @@ func (f *Framework) GenerateConfigFile(content string) string {
ExpectNoError(err)
return path
}
// WaitForTCPReady polls a TCP address until a connection succeeds or timeout.
func WaitForTCPReady(addr string, timeout time.Duration) error {
if timeout <= 0 {
return fmt.Errorf("invalid timeout for TCP readiness on %s: timeout must be positive", addr)
}
deadline := time.Now().Add(timeout)
var lastErr error
for time.Now().Before(deadline) {
conn, err := net.DialTimeout("tcp", addr, 100*time.Millisecond)
if err == nil {
conn.Close()
return nil
}
lastErr = err
time.Sleep(50 * time.Millisecond)
}
if lastErr == nil {
return fmt.Errorf("timeout waiting for TCP readiness on %s before any dial attempt", addr)
}
return fmt.Errorf("timeout waiting for TCP readiness on %s: %w", addr, lastErr)
}

View File

@@ -82,7 +82,7 @@ var _ = ginkgo.Describe("[Feature: Basic]", func() {
clientConf.WriteString(getProxyConf(test.proxyName, test.portName, test.extraConfig) + "\n")
}
// run frps and frpc
f.RunProcesses([]string{serverConf}, []string{clientConf.String()})
f.RunProcesses(serverConf, []string{clientConf.String()})
for _, test := range tests {
framework.NewRequestExpect(f).
@@ -152,7 +152,7 @@ var _ = ginkgo.Describe("[Feature: Basic]", func() {
clientConf.WriteString(getProxyConf(test.proxyName, tests[i].customDomains, test.extraConfig) + "\n")
}
// run frps and frpc
f.RunProcesses([]string{serverConf}, []string{clientConf.String()})
f.RunProcesses(serverConf, []string{clientConf.String()})
for _, test := range tests {
for domain := range strings.SplitSeq(test.customDomains, ",") {
@@ -235,7 +235,7 @@ var _ = ginkgo.Describe("[Feature: Basic]", func() {
clientConf.WriteString(getProxyConf(test.proxyName, tests[i].customDomains, test.extraConfig) + "\n")
}
// run frps and frpc
f.RunProcesses([]string{serverConf}, []string{clientConf.String()})
f.RunProcesses(serverConf, []string{clientConf.String()})
tlsConfig, err := transport.NewServerTLSConfig("", "", "")
framework.ExpectNoError(err)
@@ -419,7 +419,7 @@ var _ = ginkgo.Describe("[Feature: Basic]", func() {
}
}
// run frps and frpc
f.RunProcesses([]string{serverConf}, []string{clientServerConf.String(), clientVisitorConf.String(), clientUser2VisitorConf.String()})
f.RunProcesses(serverConf, []string{clientServerConf.String(), clientVisitorConf.String(), clientUser2VisitorConf.String()})
for _, test := range tests {
timeout := time.Second
@@ -497,7 +497,7 @@ var _ = ginkgo.Describe("[Feature: Basic]", func() {
}
// run frps and frpc
f.RunProcesses([]string{serverConf}, []string{clientConf.String()})
f.RunProcesses(serverConf, []string{clientConf.String()})
// Request without HTTP connect should get error
framework.NewRequestExpect(f).

View File

@@ -48,7 +48,7 @@ var _ = ginkgo.Describe("[Feature: ClientManage]", func() {
framework.TCPEchoServerPort, p2Port,
framework.TCPEchoServerPort, p3Port)
f.RunProcesses([]string{serverConf}, []string{clientConf})
f.RunProcesses(serverConf, []string{clientConf})
framework.NewRequestExpect(f).Port(p1Port).Ensure()
framework.NewRequestExpect(f).Port(p2Port).Ensure()
@@ -90,7 +90,7 @@ var _ = ginkgo.Describe("[Feature: ClientManage]", func() {
admin_pwd = admin
`, dashboardPort)
f.RunProcesses([]string{serverConf}, []string{clientConf})
f.RunProcesses(serverConf, []string{clientConf})
framework.NewRequestExpect(f).RequestModify(func(r *request.Request) {
r.HTTP().HTTPPath("/healthz")
@@ -116,7 +116,7 @@ var _ = ginkgo.Describe("[Feature: ClientManage]", func() {
remote_port = %d
`, adminPort, framework.TCPEchoServerPort, testPort)
f.RunProcesses([]string{serverConf}, []string{clientConf})
f.RunProcesses(serverConf, []string{clientConf})
framework.NewRequestExpect(f).Port(testPort).Ensure()

View File

@@ -76,7 +76,7 @@ func runClientServerTest(f *framework.Framework, configures *generalTestConfigur
clientConfs = append(clientConfs, client2Conf)
}
f.RunProcesses([]string{serverConf}, clientConfs)
f.RunProcesses(serverConf, clientConfs)
if configures.testDelay > 0 {
time.Sleep(configures.testDelay)

View File

@@ -33,7 +33,7 @@ var _ = ginkgo.Describe("[Feature: Config]", func() {
`, "`", "`", framework.TCPEchoServerPort, portName)
f.SetEnvs([]string{"FRP_TOKEN=123"})
f.RunProcesses([]string{serverConf}, []string{clientConf})
f.RunProcesses(serverConf, []string{clientConf})
framework.NewRequestExpect(f).PortName(portName).Ensure()
})

View File

@@ -56,7 +56,7 @@ var _ = ginkgo.Describe("[Feature: HTTP]", func() {
locations = /bar
`, fooPort, barPort)
f.RunProcesses([]string{serverConf}, []string{clientConf})
f.RunProcesses(serverConf, []string{clientConf})
tests := []struct {
path string
@@ -111,7 +111,7 @@ var _ = ginkgo.Describe("[Feature: HTTP]", func() {
custom_domains = normal.example.com
`, fooPort, barPort, otherPort)
f.RunProcesses([]string{serverConf}, []string{clientConf})
f.RunProcesses(serverConf, []string{clientConf})
// user1
framework.NewRequestExpect(f).Explain("user1").Port(vhostHTTPPort).
@@ -152,7 +152,7 @@ var _ = ginkgo.Describe("[Feature: HTTP]", func() {
http_pwd = test
`, framework.HTTPSimpleServerPort)
f.RunProcesses([]string{serverConf}, []string{clientConf})
f.RunProcesses(serverConf, []string{clientConf})
// not set auth header
framework.NewRequestExpect(f).Port(vhostHTTPPort).
@@ -188,7 +188,7 @@ var _ = ginkgo.Describe("[Feature: HTTP]", func() {
custom_domains = *.example.com
`, framework.HTTPSimpleServerPort)
f.RunProcesses([]string{serverConf}, []string{clientConf})
f.RunProcesses(serverConf, []string{clientConf})
// not match host
framework.NewRequestExpect(f).Port(vhostHTTPPort).
@@ -238,7 +238,7 @@ var _ = ginkgo.Describe("[Feature: HTTP]", func() {
subdomain = bar
`, fooPort, barPort)
f.RunProcesses([]string{serverConf}, []string{clientConf})
f.RunProcesses(serverConf, []string{clientConf})
// foo
framework.NewRequestExpect(f).Explain("foo subdomain").Port(vhostHTTPPort).
@@ -279,7 +279,7 @@ var _ = ginkgo.Describe("[Feature: HTTP]", func() {
header_X-From-Where = frp
`, localPort)
f.RunProcesses([]string{serverConf}, []string{clientConf})
f.RunProcesses(serverConf, []string{clientConf})
// not set auth header
framework.NewRequestExpect(f).Port(vhostHTTPPort).
@@ -312,7 +312,7 @@ var _ = ginkgo.Describe("[Feature: HTTP]", func() {
host_header_rewrite = rewrite.example.com
`, localPort)
f.RunProcesses([]string{serverConf}, []string{clientConf})
f.RunProcesses(serverConf, []string{clientConf})
framework.NewRequestExpect(f).Port(vhostHTTPPort).
RequestModify(func(r *request.Request) {
@@ -360,7 +360,7 @@ var _ = ginkgo.Describe("[Feature: HTTP]", func() {
custom_domains = 127.0.0.1
`, localPort)
f.RunProcesses([]string{serverConf}, []string{clientConf})
f.RunProcesses(serverConf, []string{clientConf})
u := url.URL{Scheme: "ws", Host: "127.0.0.1:" + strconv.Itoa(vhostHTTPPort)}
c, _, err := websocket.DefaultDialer.Dial(u.String(), nil)

View File

@@ -58,7 +58,7 @@ var _ = ginkgo.Describe("[Feature: Server Manager]", func() {
remote_port = 11003
`, framework.UDPEchoServerPort)
f.RunProcesses([]string{serverConf}, []string{clientConf})
f.RunProcesses(serverConf, []string{clientConf})
// TCP
// Allowed in range
@@ -97,7 +97,7 @@ var _ = ginkgo.Describe("[Feature: Server Manager]", func() {
local_port = {{ .%s }}
`, adminPort, framework.TCPEchoServerPort, framework.UDPEchoServerPort)
f.RunProcesses([]string{serverConf}, []string{clientConf})
f.RunProcesses(serverConf, []string{clientConf})
client := f.APIClientForFrpc(adminPort)
@@ -138,7 +138,7 @@ var _ = ginkgo.Describe("[Feature: Server Manager]", func() {
custom_domains = example.com
`, framework.HTTPSimpleServerPort)
f.RunProcesses([]string{serverConf}, []string{clientConf})
f.RunProcesses(serverConf, []string{clientConf})
framework.NewRequestExpect(f).RequestModify(func(r *request.Request) {
r.HTTP().HTTPHost("example.com")
@@ -165,7 +165,7 @@ var _ = ginkgo.Describe("[Feature: Server Manager]", func() {
custom_domains = example.com
`, framework.HTTPSimpleServerPort)
f.RunProcesses([]string{serverConf}, []string{clientConf})
f.RunProcesses(serverConf, []string{clientConf})
framework.NewRequestExpect(f).RequestModify(func(r *request.Request) {
r.HTTP().HTTPPath("/healthz")

View File

@@ -76,7 +76,7 @@ var _ = ginkgo.Describe("[Feature: TCPMUX httpconnect]", func() {
custom_domains = normal.example.com
`, fooPort, barPort, otherPort)
f.RunProcesses([]string{serverConf}, []string{clientConf})
f.RunProcesses(serverConf, []string{clientConf})
// user1
framework.NewRequestExpect(f).Explain("user1").
@@ -121,7 +121,7 @@ var _ = ginkgo.Describe("[Feature: TCPMUX httpconnect]", func() {
http_pwd = test
`, fooPort)
f.RunProcesses([]string{serverConf}, []string{clientConf})
f.RunProcesses(serverConf, []string{clientConf})
// not set auth header
framework.NewRequestExpect(f).Explain("no auth").
@@ -204,7 +204,7 @@ var _ = ginkgo.Describe("[Feature: TCPMUX httpconnect]", func() {
custom_domains = normal.example.com
`, localPort)
f.RunProcesses([]string{serverConf}, []string{clientConf})
f.RunProcesses(serverConf, []string{clientConf})
framework.NewRequestExpect(f).
RequestModify(func(r *request.Request) {

View File

@@ -41,7 +41,7 @@ var _ = ginkgo.Describe("[Feature: XTCP]", func() {
fallback_timeout_ms = 200
`, framework.TCPEchoServerPort, bindPortName)
f.RunProcesses([]string{serverConf}, []string{clientConf})
f.RunProcesses(serverConf, []string{clientConf})
framework.NewRequestExpect(f).
RequestModify(func(r *request.Request) {
r.Timeout(time.Second)

View File

@@ -35,7 +35,7 @@ var _ = ginkgo.Describe("[Feature: Bandwidth Limit]", func() {
bandwidth_limit = 10KB
`, localPort, remotePort)
f.RunProcesses([]string{serverConf}, []string{clientConf})
f.RunProcesses(serverConf, []string{clientConf})
content := strings.Repeat("a", 50*1024) // 5KB
start := time.Now()
@@ -89,7 +89,7 @@ var _ = ginkgo.Describe("[Feature: Bandwidth Limit]", func() {
remote_port = %d
`, localPort, remotePort)
f.RunProcesses([]string{serverConf}, []string{clientConf})
f.RunProcesses(serverConf, []string{clientConf})
content := strings.Repeat("a", 50*1024) // 5KB
start := time.Now()

View File

@@ -88,7 +88,7 @@ var _ = ginkgo.Describe("[Feature: Group]", func() {
group_key = 123
`, fooPort, remotePort, barPort, remotePort)
f.RunProcesses([]string{serverConf}, []string{clientConf})
f.RunProcesses(serverConf, []string{clientConf})
fooCount := 0
barCount := 0
@@ -144,7 +144,7 @@ var _ = ginkgo.Describe("[Feature: Group]", func() {
health_check_interval_s = 1
`, fooPort, remotePort, barPort, remotePort)
f.RunProcesses([]string{serverConf}, []string{clientConf})
f.RunProcesses(serverConf, []string{clientConf})
// check foo and bar is ok
results := []string{}
@@ -213,7 +213,7 @@ var _ = ginkgo.Describe("[Feature: Group]", func() {
health_check_url = /healthz
`, fooPort, barPort)
f.RunProcesses([]string{serverConf}, []string{clientConf})
f.RunProcesses(serverConf, []string{clientConf})
// send first HTTP request
var contents []string

View File

@@ -38,7 +38,7 @@ var _ = ginkgo.Describe("[Feature: Heartbeat]", func() {
`, serverPort, f.PortByName(framework.TCPEchoServerPort), remotePort)
// run frps and frpc
f.RunProcesses([]string{serverConf}, []string{clientConf})
f.RunProcesses(serverConf, []string{clientConf})
framework.NewRequestExpect(f).Protocol("tcp").Port(remotePort).Ensure()

View File

@@ -33,7 +33,7 @@ var _ = ginkgo.Describe("[Feature: Monitor]", func() {
remote_port = %d
`, framework.TCPEchoServerPort, remotePort)
f.RunProcesses([]string{serverConf}, []string{clientConf})
f.RunProcesses(serverConf, []string{clientConf})
framework.NewRequestExpect(f).Port(remotePort).Ensure()
time.Sleep(500 * time.Millisecond)

View File

@@ -44,7 +44,7 @@ var _ = ginkgo.Describe("[Feature: Real IP]", func() {
custom_domains = normal.example.com
`, localPort)
f.RunProcesses([]string{serverConf}, []string{clientConf})
f.RunProcesses(serverConf, []string{clientConf})
framework.NewRequestExpect(f).Port(vhostHTTPPort).
RequestModify(func(r *request.Request) {
@@ -90,7 +90,7 @@ var _ = ginkgo.Describe("[Feature: Real IP]", func() {
proxy_protocol_version = v2
`, localPort, remotePort)
f.RunProcesses([]string{serverConf}, []string{clientConf})
f.RunProcesses(serverConf, []string{clientConf})
framework.NewRequestExpect(f).Port(remotePort).Ensure(func(resp *request.Response) bool {
log.Tracef("proxy protocol get SourceAddr: %s", string(resp.Content))
@@ -136,7 +136,7 @@ var _ = ginkgo.Describe("[Feature: Real IP]", func() {
proxy_protocol_version = v2
`, localPort)
f.RunProcesses([]string{serverConf}, []string{clientConf})
f.RunProcesses(serverConf, []string{clientConf})
framework.NewRequestExpect(f).Port(vhostHTTPPort).RequestModify(func(r *request.Request) {
r.HTTP().HTTPHost("normal.example.com")

View File

@@ -70,7 +70,7 @@ var _ = ginkgo.Describe("[Feature: Client-Plugins]", func() {
clientConf.WriteString(getProxyConf(test.proxyName, test.portName, test.extraConfig) + "\n")
}
// run frps and frpc
f.RunProcesses([]string{serverConf}, []string{clientConf.String()})
f.RunProcesses(serverConf, []string{clientConf.String()})
for _, test := range tests {
framework.NewRequestExpect(f).Port(f.PortByName(test.portName)).Ensure()
@@ -92,7 +92,7 @@ var _ = ginkgo.Describe("[Feature: Client-Plugins]", func() {
plugin_http_passwd = 123
`, remotePort)
f.RunProcesses([]string{serverConf}, []string{clientConf})
f.RunProcesses(serverConf, []string{clientConf})
// http proxy, no auth info
framework.NewRequestExpect(f).PortName(framework.HTTPSimpleServerPort).RequestModify(func(r *request.Request) {
@@ -124,7 +124,7 @@ var _ = ginkgo.Describe("[Feature: Client-Plugins]", func() {
plugin_passwd = 123
`, remotePort)
f.RunProcesses([]string{serverConf}, []string{clientConf})
f.RunProcesses(serverConf, []string{clientConf})
// http proxy, no auth info
framework.NewRequestExpect(f).PortName(framework.TCPEchoServerPort).RequestModify(func(r *request.Request) {
@@ -168,7 +168,7 @@ var _ = ginkgo.Describe("[Feature: Client-Plugins]", func() {
plugin_http_passwd = 123
`, remotePort, f.TempDirectory, f.TempDirectory, f.TempDirectory)
f.RunProcesses([]string{serverConf}, []string{clientConf})
f.RunProcesses(serverConf, []string{clientConf})
// from tcp proxy
framework.NewRequestExpect(f).Request(
@@ -202,7 +202,7 @@ var _ = ginkgo.Describe("[Feature: Client-Plugins]", func() {
plugin_local_addr = 127.0.0.1:%d
`, localPort)
f.RunProcesses([]string{serverConf}, []string{clientConf})
f.RunProcesses(serverConf, []string{clientConf})
tlsConfig, err := transport.NewServerTLSConfig("", "", "")
framework.ExpectNoError(err)
@@ -246,7 +246,7 @@ var _ = ginkgo.Describe("[Feature: Client-Plugins]", func() {
plugin_key_path = %s
`, localPort, crtPath, keyPath)
f.RunProcesses([]string{serverConf}, []string{clientConf})
f.RunProcesses(serverConf, []string{clientConf})
localServer := httpserver.New(
httpserver.WithBindPort(localPort),
@@ -290,7 +290,7 @@ var _ = ginkgo.Describe("[Feature: Client-Plugins]", func() {
plugin_key_path = %s
`, localPort, crtPath, keyPath)
f.RunProcesses([]string{serverConf}, []string{clientConf})
f.RunProcesses(serverConf, []string{clientConf})
tlsConfig, err := transport.NewServerTLSConfig("", "", "")
framework.ExpectNoError(err)

View File

@@ -71,7 +71,7 @@ var _ = ginkgo.Describe("[Feature: Server-Plugins]", func() {
remote_port = %d
`, framework.TCPEchoServerPort, remotePort2)
f.RunProcesses([]string{serverConf}, []string{clientConf, invalidTokenClientConf})
f.RunProcesses(serverConf, []string{clientConf, invalidTokenClientConf})
framework.NewRequestExpect(f).Port(remotePort).Ensure()
framework.NewRequestExpect(f).Port(remotePort2).ExpectError(true).Ensure()
@@ -119,7 +119,7 @@ var _ = ginkgo.Describe("[Feature: Server-Plugins]", func() {
remote_port = %d
`, framework.TCPEchoServerPort, remotePort)
f.RunProcesses([]string{serverConf}, []string{clientConf})
f.RunProcesses(serverConf, []string{clientConf})
framework.NewRequestExpect(f).Port(remotePort).Ensure()
})
@@ -153,7 +153,7 @@ var _ = ginkgo.Describe("[Feature: Server-Plugins]", func() {
remote_port = 0
`, framework.TCPEchoServerPort)
f.RunProcesses([]string{serverConf}, []string{clientConf})
f.RunProcesses(serverConf, []string{clientConf})
framework.NewRequestExpect(f).Port(remotePort).Ensure()
})
@@ -195,7 +195,7 @@ var _ = ginkgo.Describe("[Feature: Server-Plugins]", func() {
remote_port = %d
`, framework.TCPEchoServerPort, remotePort)
_, clients := f.RunProcesses([]string{serverConf}, []string{clientConf})
_, clients := f.RunProcesses(serverConf, []string{clientConf})
framework.NewRequestExpect(f).Port(remotePort).Ensure()
@@ -250,7 +250,7 @@ var _ = ginkgo.Describe("[Feature: Server-Plugins]", func() {
remote_port = %d
`, framework.TCPEchoServerPort, remotePort)
f.RunProcesses([]string{serverConf}, []string{clientConf})
f.RunProcesses(serverConf, []string{clientConf})
framework.NewRequestExpect(f).Port(remotePort).Ensure()
@@ -297,7 +297,7 @@ var _ = ginkgo.Describe("[Feature: Server-Plugins]", func() {
remote_port = %d
`, framework.TCPEchoServerPort, remotePort)
f.RunProcesses([]string{serverConf}, []string{clientConf})
f.RunProcesses(serverConf, []string{clientConf})
framework.NewRequestExpect(f).Port(remotePort).Ensure()
@@ -342,7 +342,7 @@ var _ = ginkgo.Describe("[Feature: Server-Plugins]", func() {
remote_port = %d
`, framework.TCPEchoServerPort, remotePort)
f.RunProcesses([]string{serverConf}, []string{clientConf})
f.RunProcesses(serverConf, []string{clientConf})
framework.NewRequestExpect(f).Port(remotePort).Ensure()
@@ -389,7 +389,7 @@ var _ = ginkgo.Describe("[Feature: Server-Plugins]", func() {
remote_port = %d
`, framework.TCPEchoServerPort, remotePort)
f.RunProcesses([]string{serverConf}, []string{clientConf})
f.RunProcesses(serverConf, []string{clientConf})
framework.NewRequestExpect(f).Port(remotePort).Ensure()

View File

@@ -61,6 +61,10 @@ func (p *Process) StdOutput() string {
return p.stdOutput.String()
}
func (p *Process) Output() string {
return p.stdOutput.String() + p.errorOutput.String()
}
func (p *Process) SetBeforeStopHandler(fn func()) {
p.beforeStopHandler = fn
}

View File

@@ -35,7 +35,7 @@ var _ = ginkgo.Describe("[Feature: Annotations]", func() {
"frp.e2e.test/bar" = "value2"
`, framework.TCPEchoServerPort, p1Port)
f.RunProcesses([]string{serverConf}, []string{clientConf})
f.RunProcesses(serverConf, []string{clientConf})
framework.NewRequestExpect(f).Port(p1Port).Ensure()

View File

@@ -83,7 +83,7 @@ var _ = ginkgo.Describe("[Feature: Basic]", func() {
clientConf.WriteString(getProxyConf(test.proxyName, test.portName, test.extraConfig) + "\n")
}
// run frps and frpc
f.RunProcesses([]string{serverConf}, []string{clientConf.String()})
f.RunProcesses(serverConf, []string{clientConf.String()})
for _, test := range tests {
framework.NewRequestExpect(f).
@@ -154,7 +154,7 @@ var _ = ginkgo.Describe("[Feature: Basic]", func() {
clientConf.WriteString(getProxyConf(test.proxyName, tests[i].customDomains, test.extraConfig) + "\n")
}
// run frps and frpc
f.RunProcesses([]string{serverConf}, []string{clientConf.String()})
f.RunProcesses(serverConf, []string{clientConf.String()})
for _, test := range tests {
for domain := range strings.SplitSeq(test.customDomains, ",") {
@@ -240,7 +240,7 @@ var _ = ginkgo.Describe("[Feature: Basic]", func() {
clientConf.WriteString(getProxyConf(test.proxyName, tests[i].customDomains, test.extraConfig) + "\n")
}
// run frps and frpc
f.RunProcesses([]string{serverConf}, []string{clientConf.String()})
f.RunProcesses(serverConf, []string{clientConf.String()})
tlsConfig, err := transport.NewServerTLSConfig("", "", "")
framework.ExpectNoError(err)
@@ -426,7 +426,7 @@ var _ = ginkgo.Describe("[Feature: Basic]", func() {
}
}
// run frps and frpc
f.RunProcesses([]string{serverConf}, []string{clientServerConf.String(), clientVisitorConf.String(), clientUser2VisitorConf.String()})
f.RunProcesses(serverConf, []string{clientServerConf.String(), clientVisitorConf.String(), clientUser2VisitorConf.String()})
for _, test := range tests {
timeout := time.Second
@@ -505,7 +505,7 @@ var _ = ginkgo.Describe("[Feature: Basic]", func() {
}
// run frps and frpc
f.RunProcesses([]string{serverConf}, []string{clientConf.String()})
f.RunProcesses(serverConf, []string{clientConf.String()})
// Request without HTTP connect should get error
framework.NewRequestExpect(f).

View File

@@ -51,7 +51,7 @@ var _ = ginkgo.Describe("[Feature: ClientManage]", func() {
framework.TCPEchoServerPort, p2Port,
framework.TCPEchoServerPort, p3Port)
f.RunProcesses([]string{serverConf}, []string{clientConf})
f.RunProcesses(serverConf, []string{clientConf})
framework.NewRequestExpect(f).Port(p1Port).Ensure()
framework.NewRequestExpect(f).Port(p2Port).Ensure()
@@ -93,7 +93,7 @@ var _ = ginkgo.Describe("[Feature: ClientManage]", func() {
webServer.password = "admin"
`, dashboardPort)
f.RunProcesses([]string{serverConf}, []string{clientConf})
f.RunProcesses(serverConf, []string{clientConf})
framework.NewRequestExpect(f).RequestModify(func(r *request.Request) {
r.HTTP().HTTPPath("/healthz")
@@ -120,7 +120,7 @@ var _ = ginkgo.Describe("[Feature: ClientManage]", func() {
remotePort = %d
`, adminPort, framework.TCPEchoServerPort, testPort)
f.RunProcesses([]string{serverConf}, []string{clientConf})
f.RunProcesses(serverConf, []string{clientConf})
framework.NewRequestExpect(f).Port(testPort).Ensure()

View File

@@ -78,7 +78,7 @@ func runClientServerTest(f *framework.Framework, configures *generalTestConfigur
clientConfs = append(clientConfs, client2Conf)
}
f.RunProcesses([]string{serverConf}, clientConfs)
f.RunProcesses(serverConf, clientConfs)
if configures.testDelay > 0 {
time.Sleep(configures.testDelay)

View File

@@ -35,7 +35,7 @@ var _ = ginkgo.Describe("[Feature: Config]", func() {
`, "`", "`", framework.TCPEchoServerPort, portName)
f.SetEnvs([]string{"FRP_TOKEN=123"})
f.RunProcesses([]string{serverConf}, []string{clientConf})
f.RunProcesses(serverConf, []string{clientConf})
framework.NewRequestExpect(f).PortName(portName).Ensure()
})
@@ -69,7 +69,7 @@ var _ = ginkgo.Describe("[Feature: Config]", func() {
escapeTemplate("{{- end }}"),
)
f.RunProcesses([]string{serverConf}, []string{clientConf})
f.RunProcesses(serverConf, []string{clientConf})
client := f.APIClientForFrpc(adminPort)
checkProxyFn := func(name string, localPort, remotePort int) {
@@ -149,7 +149,7 @@ proxies:
remotePort: %d
`, port.GenName("Server"), framework.TCPEchoServerPort, remotePort)
f.RunProcesses([]string{serverConf}, []string{clientConf})
f.RunProcesses(serverConf, []string{clientConf})
framework.NewRequestExpect(f).Port(remotePort).Ensure()
})
@@ -161,7 +161,7 @@ proxies:
"proxies": [{"name": "tcp", "type": "tcp", "localPort": {{ .%s }}, "remotePort": %d}]}`,
port.GenName("Server"), framework.TCPEchoServerPort, remotePort)
f.RunProcesses([]string{serverConf}, []string{clientConf})
f.RunProcesses(serverConf, []string{clientConf})
framework.NewRequestExpect(f).Port(remotePort).Ensure()
})
})

View File

@@ -59,7 +59,7 @@ var _ = ginkgo.Describe("[Feature: HTTP]", func() {
locations = ["/bar"]
`, fooPort, barPort)
f.RunProcesses([]string{serverConf}, []string{clientConf})
f.RunProcesses(serverConf, []string{clientConf})
tests := []struct {
path string
@@ -117,7 +117,7 @@ var _ = ginkgo.Describe("[Feature: HTTP]", func() {
customDomains = ["normal.example.com"]
`, fooPort, barPort, otherPort)
f.RunProcesses([]string{serverConf}, []string{clientConf})
f.RunProcesses(serverConf, []string{clientConf})
// user1
framework.NewRequestExpect(f).Explain("user1").Port(vhostHTTPPort).
@@ -159,7 +159,7 @@ var _ = ginkgo.Describe("[Feature: HTTP]", func() {
httpPassword = "test"
`, framework.HTTPSimpleServerPort)
f.RunProcesses([]string{serverConf}, []string{clientConf})
f.RunProcesses(serverConf, []string{clientConf})
// not set auth header
framework.NewRequestExpect(f).Port(vhostHTTPPort).
@@ -196,7 +196,7 @@ var _ = ginkgo.Describe("[Feature: HTTP]", func() {
customDomains = ["*.example.com"]
`, framework.HTTPSimpleServerPort)
f.RunProcesses([]string{serverConf}, []string{clientConf})
f.RunProcesses(serverConf, []string{clientConf})
// not match host
framework.NewRequestExpect(f).Port(vhostHTTPPort).
@@ -248,7 +248,7 @@ var _ = ginkgo.Describe("[Feature: HTTP]", func() {
subdomain = "bar"
`, fooPort, barPort)
f.RunProcesses([]string{serverConf}, []string{clientConf})
f.RunProcesses(serverConf, []string{clientConf})
// foo
framework.NewRequestExpect(f).Explain("foo subdomain").Port(vhostHTTPPort).
@@ -290,7 +290,7 @@ var _ = ginkgo.Describe("[Feature: HTTP]", func() {
requestHeaders.set.x-from-where = "frp"
`, localPort)
f.RunProcesses([]string{serverConf}, []string{clientConf})
f.RunProcesses(serverConf, []string{clientConf})
framework.NewRequestExpect(f).Port(vhostHTTPPort).
RequestModify(func(r *request.Request) {
@@ -323,7 +323,7 @@ var _ = ginkgo.Describe("[Feature: HTTP]", func() {
responseHeaders.set.x-from-where = "frp"
`, localPort)
f.RunProcesses([]string{serverConf}, []string{clientConf})
f.RunProcesses(serverConf, []string{clientConf})
framework.NewRequestExpect(f).Port(vhostHTTPPort).
RequestModify(func(r *request.Request) {
@@ -357,7 +357,7 @@ var _ = ginkgo.Describe("[Feature: HTTP]", func() {
hostHeaderRewrite = "rewrite.example.com"
`, localPort)
f.RunProcesses([]string{serverConf}, []string{clientConf})
f.RunProcesses(serverConf, []string{clientConf})
framework.NewRequestExpect(f).Port(vhostHTTPPort).
RequestModify(func(r *request.Request) {
@@ -406,7 +406,7 @@ var _ = ginkgo.Describe("[Feature: HTTP]", func() {
customDomains = ["127.0.0.1"]
`, localPort)
f.RunProcesses([]string{serverConf}, []string{clientConf})
f.RunProcesses(serverConf, []string{clientConf})
u := url.URL{Scheme: "ws", Host: "127.0.0.1:" + strconv.Itoa(vhostHTTPPort)}
c, _, err := websocket.DefaultDialer.Dial(u.String(), nil)
@@ -447,7 +447,7 @@ var _ = ginkgo.Describe("[Feature: HTTP]", func() {
customDomains = ["normal.example.com"]
`, localPort)
f.RunProcesses([]string{serverConf}, []string{clientConf})
f.RunProcesses(serverConf, []string{clientConf})
framework.NewRequestExpect(f).Port(vhostHTTPPort).
RequestModify(func(r *request.Request) {

View File

@@ -67,7 +67,7 @@ var _ = ginkgo.Describe("[Feature: Server Manager]", func() {
remotePort = 11003
`, framework.UDPEchoServerPort)
f.RunProcesses([]string{serverConf}, []string{clientConf})
f.RunProcesses(serverConf, []string{clientConf})
// TCP
// Allowed in range
@@ -108,7 +108,7 @@ var _ = ginkgo.Describe("[Feature: Server Manager]", func() {
localPort = {{ .%s }}
`, adminPort, framework.TCPEchoServerPort, framework.UDPEchoServerPort)
f.RunProcesses([]string{serverConf}, []string{clientConf})
f.RunProcesses(serverConf, []string{clientConf})
client := f.APIClientForFrpc(adminPort)
@@ -150,7 +150,7 @@ var _ = ginkgo.Describe("[Feature: Server Manager]", func() {
customDomains = ["example.com"]
`, framework.HTTPSimpleServerPort)
f.RunProcesses([]string{serverConf}, []string{clientConf})
f.RunProcesses(serverConf, []string{clientConf})
framework.NewRequestExpect(f).RequestModify(func(r *request.Request) {
r.HTTP().HTTPHost("example.com")
@@ -178,7 +178,7 @@ var _ = ginkgo.Describe("[Feature: Server Manager]", func() {
customDomains = ["example.com"]
`, framework.HTTPSimpleServerPort)
f.RunProcesses([]string{serverConf}, []string{clientConf})
f.RunProcesses(serverConf, []string{clientConf})
framework.NewRequestExpect(f).RequestModify(func(r *request.Request) {
r.HTTP().HTTPPath("/healthz")

View File

@@ -79,7 +79,7 @@ var _ = ginkgo.Describe("[Feature: TCPMUX httpconnect]", func() {
customDomains = ["normal.example.com"]
`, fooPort, barPort, otherPort)
f.RunProcesses([]string{serverConf}, []string{clientConf})
f.RunProcesses(serverConf, []string{clientConf})
// user1
framework.NewRequestExpect(f).Explain("user1").
@@ -125,7 +125,7 @@ var _ = ginkgo.Describe("[Feature: TCPMUX httpconnect]", func() {
httpPassword = "test"
`, fooPort)
f.RunProcesses([]string{serverConf}, []string{clientConf})
f.RunProcesses(serverConf, []string{clientConf})
// not set auth header
framework.NewRequestExpect(f).Explain("no auth").
@@ -209,7 +209,7 @@ var _ = ginkgo.Describe("[Feature: TCPMUX httpconnect]", func() {
customDomains = ["normal.example.com"]
`, localPort)
f.RunProcesses([]string{serverConf}, []string{clientConf})
f.RunProcesses(serverConf, []string{clientConf})
framework.NewRequestExpect(f).
RequestModify(func(r *request.Request) {

View File

@@ -16,8 +16,11 @@ package basic
import (
"fmt"
"net"
"os"
"path/filepath"
"strconv"
"time"
"github.com/onsi/ginkgo/v2"
@@ -73,7 +76,7 @@ localPort = {{ .%s }}
remotePort = {{ .%s }}
`, tokenContent, framework.TCPEchoServerPort, portName)
f.RunProcesses([]string{serverConf}, []string{clientConf})
f.RunProcesses(serverConf, []string{clientConf})
framework.NewRequestExpect(f).PortName(portName).Ensure()
})
@@ -109,7 +112,7 @@ localPort = {{ .%s }}
remotePort = {{ .%s }}
`, tokenFile, framework.TCPEchoServerPort, portName)
f.RunProcesses([]string{serverConf}, []string{clientConf})
f.RunProcesses(serverConf, []string{clientConf})
framework.NewRequestExpect(f).PortName(portName).Ensure()
})
@@ -150,7 +153,7 @@ localPort = {{ .%s }}
remotePort = {{ .%s }}
`, clientTokenFile, framework.TCPEchoServerPort, portName)
f.RunProcesses([]string{serverConf}, []string{clientConf})
f.RunProcesses(serverConf, []string{clientConf})
framework.NewRequestExpect(f).PortName(portName).Ensure()
})
@@ -190,7 +193,7 @@ localPort = {{ .%s }}
remotePort = {{ .%s }}
`, clientTokenFile, framework.TCPEchoServerPort, portName)
f.RunProcesses([]string{serverConf}, []string{clientConf})
f.RunProcesses(serverConf, []string{clientConf})
// This should fail due to token mismatch - the client should not be able to connect
// We expect the request to fail because the proxy tunnel is not established
@@ -198,32 +201,27 @@ remotePort = {{ .%s }}
})
ginkgo.It("should fail with non-existent token file", func() {
// This test verifies that server fails to start when tokenSource points to non-existent file
// We'll verify this by checking that the configuration loading itself fails
// Create a config that references a non-existent file
tmpDir := f.TempDirectory
nonExistentFile := filepath.Join(tmpDir, "non_existent_token")
serverConf := consts.DefaultServerConfig
// Server config with non-existent tokenSource file
serverConf += fmt.Sprintf(`
serverPort := f.AllocPort()
serverConf := fmt.Sprintf(`
bindAddr = "0.0.0.0"
bindPort = %d
auth.tokenSource.type = "file"
auth.tokenSource.file.path = "%s"
`, nonExistentFile)
`, serverPort, nonExistentFile)
// The test expectation is that this will fail during the RunProcesses call
// because the server cannot load the configuration due to missing token file
defer func() {
if r := recover(); r != nil {
// Expected: server should fail to start due to missing file
ginkgo.By(fmt.Sprintf("Server correctly failed to start: %v", r))
}
}()
serverConfigPath := f.GenerateConfigFile(serverConf)
// This should cause a panic or error during server startup
f.RunProcesses([]string{serverConf}, []string{})
_, _, _ = f.RunFrps("-c", serverConfigPath)
// Server should have failed to start, so the port should not be listening.
conn, err := net.DialTimeout("tcp", net.JoinHostPort("127.0.0.1", strconv.Itoa(serverPort)), 1*time.Second)
if err == nil {
conn.Close()
}
framework.ExpectTrue(err != nil, "server should not be listening on port %d", serverPort)
})
})

View File

@@ -42,7 +42,7 @@ var _ = ginkgo.Describe("[Feature: XTCP]", func() {
fallbackTimeoutMs = 200
`, framework.TCPEchoServerPort, bindPortName)
f.RunProcesses([]string{serverConf}, []string{clientConf})
f.RunProcesses(serverConf, []string{clientConf})
framework.NewRequestExpect(f).
RequestModify(func(r *request.Request) {
r.Timeout(time.Second)

View File

@@ -36,7 +36,7 @@ var _ = ginkgo.Describe("[Feature: Bandwidth Limit]", func() {
transport.bandwidthLimit = "10KB"
`, localPort, remotePort)
f.RunProcesses([]string{serverConf}, []string{clientConf})
f.RunProcesses(serverConf, []string{clientConf})
content := strings.Repeat("a", 50*1024) // 5KB
start := time.Now()
@@ -92,7 +92,7 @@ var _ = ginkgo.Describe("[Feature: Bandwidth Limit]", func() {
remotePort = %d
`, localPort, remotePort)
f.RunProcesses([]string{serverConf}, []string{clientConf})
f.RunProcesses(serverConf, []string{clientConf})
content := strings.Repeat("a", 50*1024) // 5KB
start := time.Now()

View File

@@ -92,7 +92,7 @@ var _ = ginkgo.Describe("[Feature: Group]", func() {
loadBalancer.groupKey = "123"
`, fooPort, remotePort, barPort, remotePort)
f.RunProcesses([]string{serverConf}, []string{clientConf})
f.RunProcesses(serverConf, []string{clientConf})
fooCount := 0
barCount := 0
@@ -157,7 +157,7 @@ var _ = ginkgo.Describe("[Feature: Group]", func() {
loadBalancer.groupKey = "123"
`, fooPort, barPort)
f.RunProcesses([]string{serverConf}, []string{clientConf})
f.RunProcesses(serverConf, []string{clientConf})
fooCount := 0
barCount := 0
@@ -222,7 +222,7 @@ var _ = ginkgo.Describe("[Feature: Group]", func() {
loadBalancer.groupKey = "123"
`, fooPort, barPort)
f.RunProcesses([]string{serverConf}, []string{clientConf})
f.RunProcesses(serverConf, []string{clientConf})
proxyURL := fmt.Sprintf("http://127.0.0.1:%d", vhostPort)
fooCount := 0
@@ -286,7 +286,7 @@ var _ = ginkgo.Describe("[Feature: Group]", func() {
healthCheck.intervalSeconds = 1
`, fooPort, remotePort, barPort, remotePort)
f.RunProcesses([]string{serverConf}, []string{clientConf})
f.RunProcesses(serverConf, []string{clientConf})
// check foo and bar is ok
results := []string{}
@@ -357,7 +357,7 @@ var _ = ginkgo.Describe("[Feature: Group]", func() {
healthCheck.path = "/healthz"
`, fooPort, barPort)
f.RunProcesses([]string{serverConf}, []string{clientConf})
f.RunProcesses(serverConf, []string{clientConf})
// send first HTTP request
var contents []string

View File

@@ -37,7 +37,7 @@ var _ = ginkgo.Describe("[Feature: Heartbeat]", func() {
`, serverPort, f.PortByName(framework.TCPEchoServerPort), remotePort)
// run frps and frpc
f.RunProcesses([]string{serverConf}, []string{clientConf})
f.RunProcesses(serverConf, []string{clientConf})
framework.NewRequestExpect(f).Protocol("tcp").Port(remotePort).Ensure()

View File

@@ -34,7 +34,7 @@ var _ = ginkgo.Describe("[Feature: Monitor]", func() {
remotePort = %d
`, framework.TCPEchoServerPort, remotePort)
f.RunProcesses([]string{serverConf}, []string{clientConf})
f.RunProcesses(serverConf, []string{clientConf})
framework.NewRequestExpect(f).Port(remotePort).Ensure()
time.Sleep(500 * time.Millisecond)

View File

@@ -48,7 +48,7 @@ var _ = ginkgo.Describe("[Feature: Real IP]", func() {
customDomains = ["normal.example.com"]
`, localPort)
f.RunProcesses([]string{serverConf}, []string{clientConf})
f.RunProcesses(serverConf, []string{clientConf})
framework.NewRequestExpect(f).Port(vhostHTTPPort).
RequestModify(func(r *request.Request) {
@@ -82,7 +82,7 @@ var _ = ginkgo.Describe("[Feature: Real IP]", func() {
customDomains = ["normal.example.com"]
`, localPort)
f.RunProcesses([]string{serverConf}, []string{clientConf})
f.RunProcesses(serverConf, []string{clientConf})
framework.NewRequestExpect(f).Port(vhostHTTPPort).
RequestModify(func(r *request.Request) {
@@ -112,7 +112,7 @@ var _ = ginkgo.Describe("[Feature: Real IP]", func() {
localAddr = "127.0.0.1:%d"
`, localPort)
f.RunProcesses([]string{serverConf}, []string{clientConf})
f.RunProcesses(serverConf, []string{clientConf})
tlsConfig, err := transport.NewServerTLSConfig("", "", "")
framework.ExpectNoError(err)
@@ -154,7 +154,7 @@ var _ = ginkgo.Describe("[Feature: Real IP]", func() {
localAddr = "127.0.0.1:%d"
`, localPort)
f.RunProcesses([]string{serverConf}, []string{clientConf})
f.RunProcesses(serverConf, []string{clientConf})
localServer := httpserver.New(
httpserver.WithBindPort(localPort),
@@ -212,7 +212,7 @@ var _ = ginkgo.Describe("[Feature: Real IP]", func() {
transport.proxyProtocolVersion = "v2"
`, localPort, remotePort)
f.RunProcesses([]string{serverConf}, []string{clientConf})
f.RunProcesses(serverConf, []string{clientConf})
framework.NewRequestExpect(f).Port(remotePort).Ensure(func(resp *request.Response) bool {
log.Tracef("proxy protocol get SourceAddr: %s", string(resp.Content))
@@ -262,7 +262,7 @@ var _ = ginkgo.Describe("[Feature: Real IP]", func() {
transport.proxyProtocolVersion = "v2"
`, localPort, remotePort)
f.RunProcesses([]string{serverConf}, []string{clientConf})
f.RunProcesses(serverConf, []string{clientConf})
framework.NewRequestExpect(f).Protocol("udp").Port(remotePort).Ensure(func(resp *request.Response) bool {
log.Tracef("udp proxy protocol get SourceAddr: %s", string(resp.Content))
@@ -309,7 +309,7 @@ var _ = ginkgo.Describe("[Feature: Real IP]", func() {
transport.proxyProtocolVersion = "v2"
`, localPort)
f.RunProcesses([]string{serverConf}, []string{clientConf})
f.RunProcesses(serverConf, []string{clientConf})
framework.NewRequestExpect(f).Port(vhostHTTPPort).RequestModify(func(r *request.Request) {
r.HTTP().HTTPHost("normal.example.com")

View File

@@ -3,6 +3,8 @@ package features
import (
"crypto/tls"
"fmt"
"net"
"strconv"
"time"
"github.com/onsi/ginkgo/v2"
@@ -25,7 +27,8 @@ var _ = ginkgo.Describe("[Feature: SSH Tunnel]", func() {
sshTunnelGateway.bindPort = %d
`, sshPort)
f.RunProcesses([]string{serverConf}, nil)
f.RunProcesses(serverConf, nil)
framework.ExpectNoError(framework.WaitForTCPReady(net.JoinHostPort("127.0.0.1", strconv.Itoa(sshPort)), 5*time.Second))
localPort := f.PortByName(framework.TCPEchoServerPort)
remotePort := f.AllocPort()
@@ -49,7 +52,8 @@ var _ = ginkgo.Describe("[Feature: SSH Tunnel]", func() {
sshTunnelGateway.bindPort = %d
`, vhostPort, sshPort)
f.RunProcesses([]string{serverConf}, nil)
f.RunProcesses(serverConf, nil)
framework.ExpectNoError(framework.WaitForTCPReady(net.JoinHostPort("127.0.0.1", strconv.Itoa(sshPort)), 5*time.Second))
localPort := f.PortByName(framework.HTTPSimpleServerPort)
tc := ssh.NewTunnelClient(
@@ -76,7 +80,8 @@ var _ = ginkgo.Describe("[Feature: SSH Tunnel]", func() {
sshTunnelGateway.bindPort = %d
`, vhostPort, sshPort)
f.RunProcesses([]string{serverConf}, nil)
f.RunProcesses(serverConf, nil)
framework.ExpectNoError(framework.WaitForTCPReady(net.JoinHostPort("127.0.0.1", strconv.Itoa(sshPort)), 5*time.Second))
localPort := f.AllocPort()
testDomain := "test.example.com"
@@ -118,7 +123,8 @@ var _ = ginkgo.Describe("[Feature: SSH Tunnel]", func() {
sshTunnelGateway.bindPort = %d
`, tcpmuxPort, sshPort)
f.RunProcesses([]string{serverConf}, nil)
f.RunProcesses(serverConf, nil)
framework.ExpectNoError(framework.WaitForTCPReady(net.JoinHostPort("127.0.0.1", strconv.Itoa(sshPort)), 5*time.Second))
localPort := f.AllocPort()
testDomain := "test.example.com"
@@ -173,7 +179,8 @@ var _ = ginkgo.Describe("[Feature: SSH Tunnel]", func() {
bindPort = %d
`, bindPort)
f.RunProcesses([]string{serverConf}, []string{visitorConf})
f.RunProcesses(serverConf, []string{visitorConf})
framework.ExpectNoError(framework.WaitForTCPReady(net.JoinHostPort("127.0.0.1", strconv.Itoa(sshPort)), 5*time.Second))
localPort := f.PortByName(framework.TCPEchoServerPort)
tc := ssh.NewTunnelClient(

View File

@@ -30,7 +30,7 @@ var _ = ginkgo.Describe("[Feature: Store]", func() {
path = "%s/store.json"
`, adminPort, f.TempDirectory)
f.RunProcesses([]string{serverConf}, []string{clientConf})
f.RunProcesses(serverConf, []string{clientConf})
time.Sleep(500 * time.Millisecond)
proxyConfig := map[string]any{
@@ -71,7 +71,7 @@ var _ = ginkgo.Describe("[Feature: Store]", func() {
path = "%s/store.json"
`, adminPort, f.TempDirectory)
f.RunProcesses([]string{serverConf}, []string{clientConf})
f.RunProcesses(serverConf, []string{clientConf})
time.Sleep(500 * time.Millisecond)
proxyConfig := map[string]any{
@@ -125,7 +125,7 @@ var _ = ginkgo.Describe("[Feature: Store]", func() {
path = "%s/store.json"
`, adminPort, f.TempDirectory)
f.RunProcesses([]string{serverConf}, []string{clientConf})
f.RunProcesses(serverConf, []string{clientConf})
time.Sleep(500 * time.Millisecond)
proxyConfig := map[string]any{
@@ -173,7 +173,7 @@ var _ = ginkgo.Describe("[Feature: Store]", func() {
path = "%s/store.json"
`, adminPort, f.TempDirectory)
f.RunProcesses([]string{serverConf}, []string{clientConf})
f.RunProcesses(serverConf, []string{clientConf})
time.Sleep(500 * time.Millisecond)
proxyConfig := map[string]any{
@@ -225,7 +225,7 @@ var _ = ginkgo.Describe("[Feature: Store]", func() {
webServer.port = %d
`, adminPort)
f.RunProcesses([]string{serverConf}, []string{clientConf})
f.RunProcesses(serverConf, []string{clientConf})
time.Sleep(500 * time.Millisecond)
framework.NewRequestExpect(f).RequestModify(func(r *request.Request) {
@@ -247,7 +247,7 @@ var _ = ginkgo.Describe("[Feature: Store]", func() {
path = "%s/store.json"
`, adminPort, f.TempDirectory)
f.RunProcesses([]string{serverConf}, []string{clientConf})
f.RunProcesses(serverConf, []string{clientConf})
time.Sleep(500 * time.Millisecond)
invalidBody, _ := json.Marshal(map[string]any{
@@ -280,7 +280,7 @@ var _ = ginkgo.Describe("[Feature: Store]", func() {
path = "%s/store.json"
`, adminPort, f.TempDirectory)
f.RunProcesses([]string{serverConf}, []string{clientConf})
f.RunProcesses(serverConf, []string{clientConf})
time.Sleep(500 * time.Millisecond)
createBody, _ := json.Marshal(map[string]any{

View File

@@ -74,7 +74,7 @@ var _ = ginkgo.Describe("[Feature: Client-Plugins]", func() {
clientConf.WriteString(getProxyConf(test.proxyName, test.portName, test.extraConfig) + "\n")
}
// run frps and frpc
f.RunProcesses([]string{serverConf}, []string{clientConf.String()})
f.RunProcesses(serverConf, []string{clientConf.String()})
for _, test := range tests {
framework.NewRequestExpect(f).Port(f.PortByName(test.portName)).Ensure()
@@ -98,7 +98,7 @@ var _ = ginkgo.Describe("[Feature: Client-Plugins]", func() {
httpPassword = "123"
`, remotePort)
f.RunProcesses([]string{serverConf}, []string{clientConf})
f.RunProcesses(serverConf, []string{clientConf})
// http proxy, no auth info
framework.NewRequestExpect(f).PortName(framework.HTTPSimpleServerPort).RequestModify(func(r *request.Request) {
@@ -132,7 +132,7 @@ var _ = ginkgo.Describe("[Feature: Client-Plugins]", func() {
password = "123"
`, remotePort)
f.RunProcesses([]string{serverConf}, []string{clientConf})
f.RunProcesses(serverConf, []string{clientConf})
// http proxy, no auth info
framework.NewRequestExpect(f).PortName(framework.TCPEchoServerPort).RequestModify(func(r *request.Request) {
@@ -182,7 +182,7 @@ var _ = ginkgo.Describe("[Feature: Client-Plugins]", func() {
httpPassword = "123"
`, remotePort, f.TempDirectory, f.TempDirectory, f.TempDirectory)
f.RunProcesses([]string{serverConf}, []string{clientConf})
f.RunProcesses(serverConf, []string{clientConf})
// from tcp proxy
framework.NewRequestExpect(f).Request(
@@ -218,7 +218,7 @@ var _ = ginkgo.Describe("[Feature: Client-Plugins]", func() {
localAddr = "127.0.0.1:%d"
`, localPort)
f.RunProcesses([]string{serverConf}, []string{clientConf})
f.RunProcesses(serverConf, []string{clientConf})
tlsConfig, err := transport.NewServerTLSConfig("", "", "")
framework.ExpectNoError(err)
@@ -264,7 +264,7 @@ var _ = ginkgo.Describe("[Feature: Client-Plugins]", func() {
keyPath = "%s"
`, localPort, crtPath, keyPath)
f.RunProcesses([]string{serverConf}, []string{clientConf})
f.RunProcesses(serverConf, []string{clientConf})
localServer := httpserver.New(
httpserver.WithBindPort(localPort),
@@ -310,7 +310,7 @@ var _ = ginkgo.Describe("[Feature: Client-Plugins]", func() {
keyPath = "%s"
`, localPort, crtPath, keyPath)
f.RunProcesses([]string{serverConf}, []string{clientConf})
f.RunProcesses(serverConf, []string{clientConf})
tlsConfig, err := transport.NewServerTLSConfig("", "", "")
framework.ExpectNoError(err)
@@ -350,7 +350,7 @@ var _ = ginkgo.Describe("[Feature: Client-Plugins]", func() {
hostHeaderRewrite = "rewrite.test.com"
`, remotePort, localPort)
f.RunProcesses([]string{serverConf}, []string{clientConf})
f.RunProcesses(serverConf, []string{clientConf})
localServer := httpserver.New(
httpserver.WithBindPort(localPort),
@@ -385,7 +385,7 @@ var _ = ginkgo.Describe("[Feature: Client-Plugins]", func() {
requestHeaders.set.x-from-where = "frp"
`, remotePort, localPort)
f.RunProcesses([]string{serverConf}, []string{clientConf})
f.RunProcesses(serverConf, []string{clientConf})
localServer := httpserver.New(
httpserver.WithBindPort(localPort),
@@ -431,7 +431,7 @@ var _ = ginkgo.Describe("[Feature: Client-Plugins]", func() {
keyPath = "%s"
`, localPort, crtPath, keyPath)
f.RunProcesses([]string{serverConf}, []string{clientConf})
f.RunProcesses(serverConf, []string{clientConf})
localServer := httpserver.New(
httpserver.WithBindPort(localPort),

View File

@@ -74,7 +74,7 @@ var _ = ginkgo.Describe("[Feature: Server-Plugins]", func() {
remotePort = %d
`, framework.TCPEchoServerPort, remotePort2)
f.RunProcesses([]string{serverConf}, []string{clientConf, invalidTokenClientConf})
f.RunProcesses(serverConf, []string{clientConf, invalidTokenClientConf})
framework.NewRequestExpect(f).Port(remotePort).Ensure()
framework.NewRequestExpect(f).Port(remotePort2).ExpectError(true).Ensure()
@@ -124,7 +124,7 @@ var _ = ginkgo.Describe("[Feature: Server-Plugins]", func() {
remotePort = %d
`, framework.TCPEchoServerPort, remotePort)
f.RunProcesses([]string{serverConf}, []string{clientConf})
f.RunProcesses(serverConf, []string{clientConf})
framework.NewRequestExpect(f).Port(remotePort).Ensure()
})
@@ -160,7 +160,7 @@ var _ = ginkgo.Describe("[Feature: Server-Plugins]", func() {
remotePort = 0
`, framework.TCPEchoServerPort)
f.RunProcesses([]string{serverConf}, []string{clientConf})
f.RunProcesses(serverConf, []string{clientConf})
framework.NewRequestExpect(f).Port(remotePort).Ensure()
})
@@ -204,7 +204,7 @@ var _ = ginkgo.Describe("[Feature: Server-Plugins]", func() {
remotePort = %d
`, framework.TCPEchoServerPort, remotePort)
_, clients := f.RunProcesses([]string{serverConf}, []string{clientConf})
_, clients := f.RunProcesses(serverConf, []string{clientConf})
framework.NewRequestExpect(f).Port(remotePort).Ensure()
@@ -261,7 +261,7 @@ var _ = ginkgo.Describe("[Feature: Server-Plugins]", func() {
remotePort = %d
`, framework.TCPEchoServerPort, remotePort)
f.RunProcesses([]string{serverConf}, []string{clientConf})
f.RunProcesses(serverConf, []string{clientConf})
framework.NewRequestExpect(f).Port(remotePort).Ensure()
@@ -310,7 +310,7 @@ var _ = ginkgo.Describe("[Feature: Server-Plugins]", func() {
remotePort = %d
`, framework.TCPEchoServerPort, remotePort)
f.RunProcesses([]string{serverConf}, []string{clientConf})
f.RunProcesses(serverConf, []string{clientConf})
framework.NewRequestExpect(f).Port(remotePort).Ensure()
@@ -357,7 +357,7 @@ var _ = ginkgo.Describe("[Feature: Server-Plugins]", func() {
remotePort = %d
`, framework.TCPEchoServerPort, remotePort)
f.RunProcesses([]string{serverConf}, []string{clientConf})
f.RunProcesses(serverConf, []string{clientConf})
framework.NewRequestExpect(f).Port(remotePort).Ensure()
@@ -406,7 +406,7 @@ var _ = ginkgo.Describe("[Feature: Server-Plugins]", func() {
remotePort = %d
`, framework.TCPEchoServerPort, remotePort)
f.RunProcesses([]string{serverConf}, []string{clientConf})
f.RunProcesses(serverConf, []string{clientConf})
framework.NewRequestExpect(f).Port(remotePort).Ensure()