102 lines
3.7 KiB
Go
102 lines
3.7 KiB
Go
package config
|
||
|
||
import (
|
||
"encoding/json"
|
||
"testing"
|
||
)
|
||
|
||
func TestResolvePublicHTTPSPort(t *testing.T) {
|
||
t.Setenv("SMAIL_HTTP_TLS_MODE_OVERRIDE", "")
|
||
t.Setenv("SMAIL_HTTPS_PORT", "")
|
||
cases := []struct {
|
||
name string
|
||
config HTTPConfig
|
||
want int
|
||
}{
|
||
{"default direct", HTTPConfig{}, 443},
|
||
{"custom direct", HTTPConfig{HTTPSPort: 8443}, 8443},
|
||
{"https upstream", HTTPConfig{HTTPSPort: 8002, PublicHTTPSPort: 443}, 443},
|
||
{"custom public", HTTPConfig{HTTPSPort: 8002, PublicHTTPSPort: 9443}, 9443},
|
||
{"http upstream", HTTPConfig{TLSMode: HTTPSTLSModeProxy}, 443},
|
||
{"custom http upstream", HTTPConfig{TLSMode: HTTPSTLSModeProxy, PublicHTTPSPort: 9443}, 9443},
|
||
{"invalid negative", HTTPConfig{PublicHTTPSPort: -1}, -1},
|
||
{"invalid upper bound", HTTPConfig{PublicHTTPSPort: 65536}, 65536},
|
||
}
|
||
for _, test := range cases {
|
||
t.Run(test.name, func(t *testing.T) {
|
||
if got := ResolvePublicHTTPSPort(test.config); got != test.want {
|
||
t.Fatalf("公网端口为 %d,预期 %d", got, test.want)
|
||
}
|
||
})
|
||
}
|
||
}
|
||
|
||
func TestPublicHTTPSPortValidationAndSerialization(t *testing.T) {
|
||
for _, port := range []int{0, 1, 443, 8002, 65535} {
|
||
value := HTTPConfig{Port: 8001, HTTPSPort: 8002, HTTPSEnabled: true, PublicHTTPSPort: port}
|
||
if err := validateHTTP(value); err != nil {
|
||
t.Fatal(err)
|
||
}
|
||
// 公网端口不是当前进程监听端口,不能参与本机端口冲突检查。
|
||
if err := validateRuntimePorts(value, MailPorts{}); err != nil {
|
||
t.Fatal(err)
|
||
}
|
||
data, err := json.Marshal(value)
|
||
if err != nil {
|
||
t.Fatal(err)
|
||
}
|
||
var restored HTTPConfig
|
||
if err := ParseStrict(data, &restored); err != nil {
|
||
t.Fatal(err)
|
||
}
|
||
if restored.PublicHTTPSPort != port || restored.HTTPSPort != 8002 {
|
||
t.Fatalf("序列化丢失公网或内部端口:%s", data)
|
||
}
|
||
}
|
||
for _, port := range []int{-1, 65536} {
|
||
if validateHTTP(HTTPConfig{PublicHTTPSPort: port}) == nil {
|
||
t.Fatalf("接受了非法公网端口 %d", port)
|
||
}
|
||
}
|
||
}
|
||
|
||
func TestPublicHTTPSPortRuntimeAccess(t *testing.T) {
|
||
oldInstance, oldSnapshot, oldManager := Instance, CurrentConfig(), CurrentManager()
|
||
t.Cleanup(func() {
|
||
Instance = oldInstance
|
||
PublishConfigSnapshot(oldSnapshot)
|
||
SetRuntimeManager(oldManager)
|
||
})
|
||
SetRuntimeManager(nil)
|
||
PublishConfigSnapshot(&Config{HttpPort: 8001, HttpsPort: 8002, PublicHTTPSPort: 443})
|
||
if got := CurrentHTTPConfig(); got.PublicHTTPSPort != 443 || got.HTTPSPort != 8002 {
|
||
t.Fatalf("旧配置运行时映射丢失端口:%+v", got)
|
||
}
|
||
runtime := validRuntimeConfig()
|
||
runtime.Root.HTTP = HTTPConfig{Port: 8001, HTTPSPort: 8002, HTTPSEnabled: true, PublicHTTPSPort: 9443}
|
||
SetRuntimeManager(&ConfigManager{snapshots: runtimeAccessSnapshotStore{runtime: runtime}})
|
||
if got := CurrentHTTPConfig(); got.PublicHTTPSPort != 9443 || got.HTTPSPort != 8002 {
|
||
t.Fatalf("分区配置运行时映射丢失端口:%+v", got)
|
||
}
|
||
}
|
||
|
||
func TestWebAuthnUsesPublicHTTPSPort(t *testing.T) {
|
||
root := RootConfig{Domains: DomainConfig{Web: "mail.example.com"}, HTTP: HTTPConfig{HTTPSPort: 8002, PublicHTTPSPort: 443}}
|
||
for _, test := range []struct {
|
||
port int
|
||
want string
|
||
}{{443, "https://mail.example.com"}, {9443, "https://mail.example.com:9443"}, {0, "https://mail.example.com:8002"}} {
|
||
root.HTTP.PublicHTTPSPort = test.port
|
||
security, err := ResolveWebAuthnSecurity(root)
|
||
if err != nil || len(security.WebAuthnRPOrigins) != 1 || security.WebAuthnRPOrigins[0] != test.want {
|
||
t.Fatalf("安全密钥默认来源不匹配:%+v,%v", security, err)
|
||
}
|
||
}
|
||
root.HTTP.PublicHTTPSPort = 443
|
||
root.Security.WebAuthnRPOrigins = []string{"https://mail.example.com:9443"}
|
||
security, err := ResolveWebAuthnSecurity(root)
|
||
if err != nil || security.WebAuthnRPOrigins[0] != root.Security.WebAuthnRPOrigins[0] {
|
||
t.Fatal("公网端口覆盖了显式配置的安全密钥来源")
|
||
}
|
||
}
|