Files
go_blog/config/config_test.go
T

142 lines
4.1 KiB
Go
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
package config
import (
"bytes"
"os"
"path/filepath"
"strings"
"testing"
"gopkg.in/yaml.v3"
)
// TestConfigFileCreatedNotWorldReadable 覆盖 SECURITY_TODO #11
// 配置文件(内嵌会话密钥)不得被组/其他用户读取。
func TestConfigFileCreatedNotWorldReadable(t *testing.T) {
path := filepath.Join(t.TempDir(), "config.yaml")
LoadConfig(path)
st, err := os.Stat(path)
if err != nil {
t.Fatalf("config file not created: %v", err)
}
if perm := st.Mode().Perm(); perm != 0640 {
t.Fatalf("config perms = %v, want 0640", perm)
}
}
func TestMySQLDSN(t *testing.T) {
d := &DatabaseConfig{
DBName: "blog_go",
Username: "user",
Password: "pass:word",
Host: "127.0.0.1",
Port: "3306",
}
want := "user:pass:word@tcp(127.0.0.1:3306)/blog_go?charset=utf8mb4&parseTime=True&loc=Local"
if got := d.MySQLDSN(); got != want {
t.Fatalf("MySQLDSN() = %q, want %q", got, want)
}
}
// TestLoadConfigFillsMissingKeys 覆盖启动时补齐缺失配置项并回写文件:
// 旧格式配置(无 database 段)应被补全,且不覆盖已存在的 path。
func TestLoadConfigFillsMissingKeys(t *testing.T) {
path := filepath.Join(t.TempDir(), "config.yaml")
secret := strings.Repeat("a", 64)
old := "secret: " + secret + "\npath: ./data\n"
if err := os.WriteFile(path, []byte(old), 0640); err != nil {
t.Fatalf("write config: %v", err)
}
cfg := LoadConfig(path)
if cfg.Database.Type != "sqlite" || cfg.Database.DBName != mysqlExampleDBName ||
cfg.Database.Username != mysqlExampleUser || cfg.Database.Password != mysqlExamplePassword ||
cfg.Database.Host != mysqlExampleHost || cfg.Database.Port != mysqlExamplePort {
t.Fatalf("database defaults not filled: %+v", cfg.Database)
}
if cfg.Web.Port != defaultPort {
t.Fatalf("web port = %q, want %q", cfg.Web.Port, defaultPort)
}
if cfg.Path != "./data" {
t.Fatalf("path = %q, want ./data (must not be overwritten)", cfg.Path)
}
st, err := os.Stat(path)
if err != nil {
t.Fatalf("stat config: %v", err)
}
if perm := st.Mode().Perm(); perm != 0640 {
t.Fatalf("config perms = %v, want 0640", perm)
}
data, err := os.ReadFile(path)
if err != nil {
t.Fatalf("read config: %v", err)
}
back := &Config{}
if err := yaml.Unmarshal(data, back); err != nil {
t.Fatalf("reload config: %v", err)
}
if back.Database.DBName != mysqlExampleDBName {
t.Fatalf("rewritten file db_name = %q, want %q", back.Database.DBName, mysqlExampleDBName)
}
}
// TestLoadConfigKeepsCompleteFile 覆盖配置完整时不回写文件。
func TestLoadConfigKeepsCompleteFile(t *testing.T) {
path := filepath.Join(t.TempDir(), "config.yaml")
content := "database:\n" +
" type: mysql\n" +
" db_name: myblog\n" +
" username: root\n" +
" password: p@ss\n" +
" host: db.local\n" +
" port: \"3307\"\n" +
"web:\n" +
" port: \"8080\"\n" +
" socket: \"\"\n" +
" trusted_proxies:\n" +
" - 127.0.0.1\n" +
" - ::1\n" +
"path: ./data\n" +
"secret: " + strings.Repeat("a", 64) + "\n"
if err := os.WriteFile(path, []byte(content), 0640); err != nil {
t.Fatalf("write config: %v", err)
}
cfg := LoadConfig(path)
if cfg.Database.Password != "p@ss" {
t.Fatalf("password = %q, want p@ss (must not be overwritten)", cfg.Database.Password)
}
after, err := os.ReadFile(path)
if err != nil {
t.Fatalf("read config: %v", err)
}
if !bytes.Equal(after, []byte(content)) {
t.Fatalf("complete config file was rewritten:\n%s", after)
}
}
// TestLoadConfigMalformedNoRewrite 覆盖解析失败的配置文件不被回写。
func TestLoadConfigMalformedNoRewrite(t *testing.T) {
path := filepath.Join(t.TempDir(), "config.yaml")
// web.port 为序列不能解码到 stringyaml.Unmarshal 报错。
content := "secret: " + strings.Repeat("a", 64) + "\nweb:\n port: [8080]\n"
if err := os.WriteFile(path, []byte(content), 0640); err != nil {
t.Fatalf("write config: %v", err)
}
LoadConfig(path)
after, err := os.ReadFile(path)
if err != nil {
t.Fatalf("read config: %v", err)
}
if !bytes.Equal(after, []byte(content)) {
t.Fatalf("malformed config was rewritten:\n%s", after)
}
}