Files
Havline/internal/frp/agent_tunnel_test.go
T

68 lines
1.8 KiB
Go
Raw Normal View History

package frp
import (
"context"
"fmt"
"net"
"testing"
"time"
)
func TestAgentTunnelBindsLoopbackAndReleasesPort(t *testing.T) {
probe, err := net.Listen("tcp", "127.0.0.1:0")
if err != nil {
t.Fatal(err)
}
port := probe.Addr().(*net.TCPAddr).Port
_ = probe.Close()
tunnel := newAgentTunnel(context.Background(), 1, port, SSHInstaller{})
if err := tunnel.Start(); err != nil {
t.Fatal(err)
}
if _, err := net.Listen("tcp", fmt.Sprintf("127.0.0.1:%d", port)); err == nil {
t.Fatal("隧道启动后本地端口应已被占用")
}
state, _ := tunnel.State()
2026-10-07 19:26:02 +08:00
if state != "connecting" && state != "connected" && state != "reconnecting" {
t.Fatalf("state=%q, want connecting、connected 或 reconnecting", state)
}
tunnel.Stop()
if listener, err := net.Listen("tcp", fmt.Sprintf("127.0.0.1:%d", port)); err != nil {
t.Fatalf("隧道停止后端口未释放: %v", err)
} else {
_ = listener.Close()
}
}
func TestNextTunnelBackoff(t *testing.T) {
cases := []struct {
in time.Duration
want time.Duration
}{
{0, agentTunnelBackoffMin},
{time.Second, 2 * time.Second},
{40 * time.Second, agentTunnelBackoffMax},
{agentTunnelBackoffMax, agentTunnelBackoffMax},
}
for _, tc := range cases {
if got := nextTunnelBackoff(tc.in); got != tc.want {
t.Fatalf("nextTunnelBackoff(%v) = %v, 期望 %v", tc.in, got, tc.want)
}
}
}
2026-10-07 19:26:02 +08:00
func TestAgentTunnelStopClosesActiveConnections(t *testing.T) {
tunnel := newAgentTunnel(context.Background(), 1, 0, SSHInstaller{})
server, client := net.Pipe()
defer client.Close()
if !tunnel.trackConn(server) {
t.Fatal("隧道运行时应能登记活动连接")
}
tunnel.Stop()
_ = client.SetReadDeadline(time.Now().Add(time.Second))
if _, err := client.Read(make([]byte, 1)); err == nil {
t.Fatal("隧道停止后活动连接应被关闭")
}
}