Some checks are pending
Security Checks / security (push) Waiting to run
统一 frontend、backend、test、test-log 和 out 目录,更新构建、部署及测试入口;纳入配置管理兼容与首次安全引导修复;排除本机配置、密钥和测试产物。
106 lines
3.2 KiB
Go
106 lines
3.2 KiB
Go
package config
|
|
|
|
import (
|
|
"encoding/json"
|
|
"strings"
|
|
"testing"
|
|
"time"
|
|
)
|
|
|
|
func TestDatabaseTypeDefaultsAndValidation(t *testing.T) {
|
|
secret := StoredSecret{Ciphertext: "enc:v1:stored", Version: 1, UpdatedAt: time.Now().UTC()}
|
|
tests := []struct {
|
|
name string
|
|
typeValue DatabaseType
|
|
port uint16
|
|
wantPort uint16
|
|
}{
|
|
{name: "mysql default", typeValue: DatabaseTypeMySQL, wantPort: DefaultMySQLPort},
|
|
{name: "postgresql default", typeValue: DatabaseTypePostgreSQL, wantPort: DefaultPostgreSQLPort},
|
|
}
|
|
for _, test := range tests {
|
|
t.Run(test.name, func(t *testing.T) {
|
|
got := NormalizeDatabaseConfig(DatabaseConfig{Type: test.typeValue})
|
|
if got.Port != test.wantPort {
|
|
t.Fatalf("default port = %d, want %d", got.Port, test.wantPort)
|
|
}
|
|
valid := got
|
|
valid.Host = "127.0.0.1"
|
|
valid.Username = "smail"
|
|
valid.Password = secret
|
|
valid.Name = "smail"
|
|
if err := ValidateDatabaseConfig(valid); err != nil {
|
|
t.Fatalf("valid database rejected: %v", err)
|
|
}
|
|
})
|
|
}
|
|
if _, ok := DefaultDatabasePort(DatabaseTypeSQLite); ok {
|
|
t.Fatal("SQLite unexpectedly received a network default port")
|
|
}
|
|
if DatabaseType("postgres").Valid() {
|
|
t.Fatal("legacy PostgreSQL enum was accepted")
|
|
}
|
|
}
|
|
|
|
func TestSQLiteLocalRefIsBackendReferenceOnly(t *testing.T) {
|
|
valid := DatabaseConfig{Type: DatabaseTypeSQLite, LocalRef: "smail.db"}
|
|
if err := ValidateDatabaseConfig(valid); err != nil {
|
|
t.Fatalf("valid SQLite database rejected: %v", err)
|
|
}
|
|
for _, localRef := range []string{
|
|
"../smail.db",
|
|
"config/smail.db",
|
|
"C:\\data\\smail.db",
|
|
"/var/lib/smail/smail.db",
|
|
"\\\\server\\share\\smail.db",
|
|
"",
|
|
} {
|
|
t.Run(localRef, func(t *testing.T) {
|
|
candidate := valid
|
|
candidate.LocalRef = localRef
|
|
if err := ValidateDatabaseConfig(candidate); err == nil {
|
|
t.Fatalf("arbitrary localRef %q was accepted", localRef)
|
|
}
|
|
})
|
|
}
|
|
for name, mutate := range map[string]func(*DatabaseConfig){
|
|
"host": func(candidate *DatabaseConfig) { candidate.Host = "127.0.0.1" },
|
|
"port": func(candidate *DatabaseConfig) { candidate.Port = 3306 },
|
|
"username": func(candidate *DatabaseConfig) { candidate.Username = "smail" },
|
|
"name": func(candidate *DatabaseConfig) { candidate.Name = "smail" },
|
|
"password": func(candidate *DatabaseConfig) {
|
|
candidate.Password = StoredSecret{Ciphertext: "enc:v1:secret", Version: 1, UpdatedAt: time.Now().UTC()}
|
|
},
|
|
} {
|
|
t.Run(name, func(t *testing.T) {
|
|
candidate := valid
|
|
mutate(&candidate)
|
|
if err := ValidateDatabaseConfig(candidate); err == nil {
|
|
t.Fatalf("SQLite %s field was accepted", name)
|
|
}
|
|
})
|
|
}
|
|
}
|
|
|
|
func TestDatabaseModelSerializationUsesLocalRef(t *testing.T) {
|
|
root := testRootConfig()
|
|
data, err := json.Marshal(root)
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
encoded := string(data)
|
|
if !strings.Contains(encoded, `"localRef":"smail.db"`) {
|
|
t.Fatalf("serialized database omitted localRef: %s", encoded)
|
|
}
|
|
if strings.Contains(encoded, "sqliteLocalRef") {
|
|
t.Fatalf("serialized database contains legacy SQLite field: %s", encoded)
|
|
}
|
|
var decoded RootConfig
|
|
if err := ParseStrict(data, &decoded); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
if decoded.Database.LocalRef != "smail.db" {
|
|
t.Fatalf("decoded localRef = %q", decoded.Database.LocalRef)
|
|
}
|
|
}
|