mirror of
https://github.com/fatedier/frp.git
synced 2026-03-17 23:39:16 +08:00
test/e2e: replace RunProcesses client sleep with log-based proxy readiness detection (#5226)
* test/e2e: replace RunProcesses client sleep with log-based proxy readiness detection Replace the fixed 1500ms sleep in RunProcesses with event-driven proxy registration detection by monitoring frpc log output for "start proxy success" messages. Key changes: - Add thread-safe SafeBuffer to replace bytes.Buffer in Process, enabling concurrent read/write of process output during execution - Add Process.WaitForOutput() to poll process output for pattern matches with timeout and early exit on process termination - Add waitForClientProxyReady() that uses config.LoadClientConfig() to extract proxy names, then waits for each proxy's success log - For visitor-only clients (no deterministic readiness signal), fall back to the original sleep with elapsed time deducted * test/e2e: use shared deadline for proxy readiness and fix doc comment - Use a single deadline in waitForClientProxyReady so total wait across all proxies does not exceed the given timeout - Fix WaitForOutput doc comment to accurately describe single pattern with count semantics
This commit is contained in:
@@ -9,6 +9,7 @@ import (
|
||||
"strconv"
|
||||
"time"
|
||||
|
||||
"github.com/fatedier/frp/pkg/config"
|
||||
flog "github.com/fatedier/frp/pkg/util/log"
|
||||
"github.com/fatedier/frp/test/e2e/framework/consts"
|
||||
"github.com/fatedier/frp/test/e2e/pkg/process"
|
||||
@@ -61,9 +62,22 @@ func (f *Framework) RunProcesses(serverTemplate string, clientTemplates []string
|
||||
err = p.Start()
|
||||
ExpectNoError(err)
|
||||
}
|
||||
// frpc needs time to connect and register proxies with frps.
|
||||
if len(clientProcesses) > 0 {
|
||||
time.Sleep(1500 * time.Millisecond)
|
||||
// Wait for each client's proxies to register with frps.
|
||||
// If any client has no proxies (e.g. visitor-only), fall back to sleep
|
||||
// for the remaining time since visitors have no deterministic readiness signal.
|
||||
allConfirmed := len(clientProcesses) > 0
|
||||
start := time.Now()
|
||||
for i, p := range clientProcesses {
|
||||
configPath := f.clientConfPaths[len(f.clientConfPaths)-len(clientProcesses)+i]
|
||||
if !waitForClientProxyReady(configPath, p, 5*time.Second) {
|
||||
allConfirmed = false
|
||||
}
|
||||
}
|
||||
if len(clientProcesses) > 0 && !allConfirmed {
|
||||
remaining := 1500*time.Millisecond - time.Since(start)
|
||||
if remaining > 0 {
|
||||
time.Sleep(remaining)
|
||||
}
|
||||
}
|
||||
|
||||
return serverProcess, clientProcesses
|
||||
@@ -105,6 +119,31 @@ func (f *Framework) GenerateConfigFile(content string) string {
|
||||
return path
|
||||
}
|
||||
|
||||
// waitForClientProxyReady parses the client config to extract proxy names,
|
||||
// then waits for each proxy's "start proxy success" log in the process output.
|
||||
// Returns true only if proxies were expected and all registered successfully.
|
||||
func waitForClientProxyReady(configPath string, p *process.Process, timeout time.Duration) bool {
|
||||
_, proxyCfgs, _, _, err := config.LoadClientConfig(configPath, false)
|
||||
if err != nil || len(proxyCfgs) == 0 {
|
||||
return false
|
||||
}
|
||||
|
||||
// Use a single deadline so the total wait across all proxies does not exceed timeout.
|
||||
deadline := time.Now().Add(timeout)
|
||||
for _, cfg := range proxyCfgs {
|
||||
remaining := time.Until(deadline)
|
||||
if remaining <= 0 {
|
||||
return false
|
||||
}
|
||||
name := cfg.GetBaseConfig().Name
|
||||
pattern := fmt.Sprintf("[%s] start proxy success", name)
|
||||
if err := p.WaitForOutput(pattern, 1, remaining); err != nil {
|
||||
return false
|
||||
}
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
// WaitForTCPReady polls a TCP address until a connection succeeds or timeout.
|
||||
func WaitForTCPReady(addr string, timeout time.Duration) error {
|
||||
if timeout <= 0 {
|
||||
|
||||
Reference in New Issue
Block a user