Files
Havline/internal/frp/config_test.go
T

92 lines
3.9 KiB
Go
Raw Normal View History

2026-09-23 09:40:59 +08:00
package frp
import (
2026-10-07 19:26:02 +08:00
"encoding/json"
2026-09-23 09:40:59 +08:00
"strings"
"testing"
)
func TestRenderTOML(t *testing.T) {
remotePort := 60022
content := renderTOML(renderedConfig{
Server: Server{ServerAddr: "vps.example.com", ServerPort: 7000, TLS: true},
Token: "token with \"quotes\"",
Proxies: []Proxy{
{Name: "nas-ssh", Type: "tcp", LocalIP: "127.0.0.1", LocalPort: 22, RemotePort: &remotePort},
{Name: "nas-web", Type: "http", LocalIP: "127.0.0.1", LocalPort: 18080, CustomDomains: []string{"nas.example.com"}},
},
})
for _, expected := range []string{
`serverAddr = "vps.example.com"`,
`auth.token = "token with \"quotes\""`,
`remotePort = 60022`,
`customDomains = ["nas.example.com"]`,
} {
if !strings.Contains(content, expected) {
t.Fatalf("配置缺少 %q:\n%s", expected, content)
}
}
}
func TestRenderMaskedTOMLDoesNotExposeToken(t *testing.T) {
content := renderMaskedTOML(Server{ServerAddr: "vps.example.com", ServerPort: 7000, TLS: true}, nil)
if !strings.Contains(content, `auth.token = "********"`) {
t.Fatalf("脱敏配置未隐藏 Token:\n%s", content)
}
}
func TestRenderProxyOptions(t *testing.T) {
content := renderTOML(renderedConfig{Server: Server{ServerAddr: "vps.example.com", ServerPort: 7000}, Proxies: []Proxy{
{Name: "udp", Type: "udp", LocalIP: "127.0.0.1", LocalPort: 53, RemotePort: intPtr(6002), Options: ProxyOptions{Transport: ProxyTransportOptions{UseEncryption: true, ProxyProtocolVersion: "v2"}, HealthCheck: ProxyHealthCheckOptions{Type: "tcp"}}},
{Name: "secret", Type: "stcp", LocalIP: "127.0.0.1", LocalPort: 22, Options: ProxyOptions{SecretKey: "secret", AllowUsers: []string{"*"}}},
}})
for _, expected := range []string{`type = "udp"`, `remotePort = 6002`, `transport.useEncryption = true`, `transport.proxyProtocolVersion = "v2"`, `healthCheck.type = "tcp"`, `secretKey = "secret"`, `allowUsers = ["*"]`} {
if !strings.Contains(content, expected) {
t.Fatalf("配置缺少 %q:\n%s", expected, content)
}
}
}
func TestRenderNATTraversalOnlyWhenDisabledAssistedAddrs(t *testing.T) {
omitted := renderTOML(renderedConfig{Proxies: []Proxy{
{Name: "p2p", Type: "xtcp", Options: ProxyOptions{NATTraversal: &ProxyNATTraversal{}}},
}})
if strings.Contains(omitted, "natTraversal") {
t.Fatalf("disableAssistedAddrs=false 不应渲染 natTraversal(旧版 frpc 校验会失败):\n%s", omitted)
}
enabled := renderTOML(renderedConfig{Proxies: []Proxy{
{Name: "p2p", Type: "xtcp", Options: ProxyOptions{NATTraversal: &ProxyNATTraversal{DisableAssistedAddrs: true}}},
}})
if !strings.Contains(enabled, "natTraversal.disableAssistedAddrs = true") {
t.Fatalf("disableAssistedAddrs=true 应渲染 natTraversal:\n%s", enabled)
}
}
2026-10-07 19:26:02 +08:00
// 旧数据(config_json = "{}")缺省布尔键时必须补回表单默认值,
// 否则会生成 transport.tcpMux = false,让每条新连接都重建 TCP+TLS。
func TestServerOptionsBooleanDefaultsWhenKeysMissing(t *testing.T) {
var legacy ServerOptions
if err := json.Unmarshal([]byte("{}"), &legacy); err != nil {
t.Fatalf("解析旧版空配置失败:%v", err)
}
legacy = normalizeServerOptions(legacy)
if !legacy.TCPMux || !legacy.LoginFailExit {
t.Fatalf("缺省键应补默认值 true,实际 tcpMux=%v loginFailExit=%v", legacy.TCPMux, legacy.LoginFailExit)
}
content := renderTOML(renderedConfig{Server: Server{ServerAddr: "vps.example.com", ServerPort: 7000, Options: legacy}})
if !strings.Contains(content, "transport.tcpMux = true") {
t.Fatalf("旧版配置应渲染 transport.tcpMux = true:\n%s", content)
}
var explicit ServerOptions
if err := json.Unmarshal([]byte(`{"tcp_mux":false,"login_fail_exit":false}`), &explicit); err != nil {
t.Fatalf("解析显式配置失败:%v", err)
}
if explicit.TCPMux || explicit.LoginFailExit {
t.Fatalf("显式 false 不应被默认值覆盖,实际 tcpMux=%v loginFailExit=%v", explicit.TCPMux, explicit.LoginFailExit)
}
}
2026-09-23 09:40:59 +08:00
func intPtr(value int) *int { return &value }