112 lines
3.2 KiB
Go
112 lines
3.2 KiB
Go
package data
|
|
|
|
import (
|
|
"context"
|
|
"os"
|
|
"path/filepath"
|
|
"strings"
|
|
"testing"
|
|
|
|
"kra/internal/conf"
|
|
|
|
"gopkg.in/yaml.v3"
|
|
)
|
|
|
|
func TestDatabaseConnectionConfigured(t *testing.T) {
|
|
tests := []struct {
|
|
name string
|
|
config *conf.Data_Database
|
|
want bool
|
|
}{
|
|
{name: "missing config", config: nil, want: false},
|
|
{name: "empty database", config: &conf.Data_Database{Driver: "mysql"}, want: false},
|
|
{name: "named database", config: &conf.Data_Database{Driver: "mysql", Name: "kra"}, want: true},
|
|
{name: "standalone DSN", config: &conf.Data_Database{Driver: "sqlite", Source: "file:kra.db"}, want: true},
|
|
{name: "generated DSN still requires a name", config: &conf.Data_Database{Driver: "mysql", Source: "root@tcp(localhost)/", Host: "localhost"}, want: false},
|
|
}
|
|
for _, test := range tests {
|
|
t.Run(test.name, func(t *testing.T) {
|
|
if got := databaseConnectionConfigured(test.config); got != test.want {
|
|
t.Fatalf("databaseConnectionConfigured() = %v, want %v", got, test.want)
|
|
}
|
|
})
|
|
}
|
|
}
|
|
|
|
func TestInitializationStateTracksRealDatabaseConnection(t *testing.T) {
|
|
data := &Data{}
|
|
repo := &initializationRepo{data: data}
|
|
|
|
initialized, err := repo.IsInitialized(context.Background())
|
|
if err != nil {
|
|
t.Fatalf("IsInitialized() error = %v", err)
|
|
}
|
|
if initialized {
|
|
t.Fatal("bootstrap state must require initialization")
|
|
}
|
|
|
|
data.databaseReady.Store(true)
|
|
initialized, err = repo.IsInitialized(context.Background())
|
|
if err != nil {
|
|
t.Fatalf("IsInitialized() error = %v", err)
|
|
}
|
|
if !initialized {
|
|
t.Fatal("an active configured database must not require initialization")
|
|
}
|
|
}
|
|
|
|
func TestPersistDatabaseConfigPreservesTemplateAndRotatesJWTKey(t *testing.T) {
|
|
root := t.TempDir()
|
|
configPath := filepath.Join(root, "config.yaml")
|
|
original := `server:
|
|
http:
|
|
addr: 0.0.0.0:8000
|
|
data:
|
|
database:
|
|
driver: mysql
|
|
name: old
|
|
redis:
|
|
addr: 127.0.0.1:6379
|
|
admin:
|
|
jwt:
|
|
signing_key: old-key
|
|
issuer: kra
|
|
zap:
|
|
director: logs
|
|
extension:
|
|
preserved: true
|
|
`
|
|
if err := os.WriteFile(configPath, []byte(original), 0o600); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
runtime := conf.NewRuntime(&conf.Data{}, &conf.AdminBackend{ConfigPath: configPath})
|
|
data := &Data{runtime: runtime}
|
|
if err := data.persistDatabaseConfig(&conf.Data_Database{Driver: "mysql", Host: "db", Port: "3306", User: "root", Password: "secret", Name: "kra", Config: "parseTime=True"}, "new-key"); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
raw, err := os.ReadFile(configPath)
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
var value map[string]any
|
|
if err = yaml.Unmarshal(raw, &value); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
admin := value["admin"].(map[string]any)
|
|
jwt := admin["jwt"].(map[string]any)
|
|
if jwt["signing_key"] != "new-key" || jwt["issuer"] != "kra" {
|
|
t.Fatalf("unexpected jwt config: %#v", jwt)
|
|
}
|
|
dataConfig := value["data"].(map[string]any)
|
|
database := dataConfig["database"].(map[string]any)
|
|
if database["name"] != "kra" || database["password"] != "secret" {
|
|
t.Fatalf("unexpected database config: %#v", database)
|
|
}
|
|
if _, ok := dataConfig["redis"]; !ok {
|
|
t.Fatalf("redis config was removed: %#v", dataConfig)
|
|
}
|
|
if _, ok := value["extension"]; !ok || !strings.Contains(string(raw), "preserved: true") {
|
|
t.Fatalf("extension config was removed: %s", raw)
|
|
}
|
|
}
|