package config import ( "os" "path/filepath" "testing" "time" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" "gopkg.in/yaml.v3" ) func TestLoadDesktopConfigAtPath_WithMetadata(t *testing.T) { dir := t.TempDir() configPath := filepath.Join(dir, "config.yaml") cfg := DefaultConfig() cfg.Server.Port = 8888 data, err := yaml.Marshal(cfg) require.NoError(t, err) require.NoError(t, os.WriteFile(configPath, data, 0o600)) loaded, meta, err := loadConfigWithMetadata(loadOptions{ configPathOverride: configPath, useCLI: false, useEnv: false, useConfigFlag: false, }) require.NoError(t, err) assert.Equal(t, 8888, loaded.Server.Port) assert.Equal(t, configPath, meta.ConfigPath) } func TestSaveConfigToPath(t *testing.T) { dir := t.TempDir() configPath := filepath.Join(dir, "sub", "config.yaml") cfg := DefaultConfig() cfg.Server.Port = 7777 err := SaveConfigToPath(cfg, configPath) require.NoError(t, err) data, err := os.ReadFile(configPath) require.NoError(t, err) assert.Contains(t, string(data), "7777") } func TestSaveConfigToPath_InvalidDir(t *testing.T) { cfg := DefaultConfig() err := SaveConfigToPath(cfg, "/dev/null/impossible/config.yaml") assert.Error(t, err) } func TestDurationConversion(t *testing.T) { cfg := DefaultConfig() dto := configToDTO(cfg) parsed, err := time.ParseDuration(dto.Server.ReadTimeout) require.NoError(t, err) assert.Equal(t, cfg.Server.ReadTimeout, parsed) parsed, err = time.ParseDuration(dto.Database.ConnMaxLifetime) require.NoError(t, err) assert.Equal(t, cfg.Database.ConnMaxLifetime, parsed) } func TestSaveConfigToPath_DurationFormat(t *testing.T) { dir := t.TempDir() configPath := filepath.Join(dir, "config.yaml") cfg := DefaultConfig() cfg.Server.ReadTimeout = 30 * time.Second cfg.Server.WriteTimeout = 1 * time.Minute cfg.Database.ConnMaxLifetime = 1 * time.Hour err := SaveConfigToPath(cfg, configPath) require.NoError(t, err) data, err := os.ReadFile(configPath) require.NoError(t, err) content := string(data) assert.Contains(t, content, "conn_max_lifetime: 1h0m0s") assert.Contains(t, content, "read_timeout: 30s") assert.Contains(t, content, "write_timeout: 1m0s") } func TestSaveAndReload_DurationRoundTrip(t *testing.T) { dir := t.TempDir() configPath := filepath.Join(dir, "config.yaml") yamlContent := ` server: port: 9826 read_timeout: 30s write_timeout: 1m database: driver: sqlite path: ` + filepath.Join(dir, "test.db") + ` max_idle_conns: 10 max_open_conns: 100 conn_max_lifetime: 30m log: level: info path: ` + filepath.Join(dir, "log") + ` max_size: 100 max_backups: 10 max_age: 30 compress: true ` require.NoError(t, os.WriteFile(configPath, []byte(yamlContent), 0o600)) cfg, err := LoadDesktopConfigAtPath(configPath) require.NoError(t, err) assert.Equal(t, 30*time.Minute, cfg.Database.ConnMaxLifetime) err = SaveConfigToPath(cfg, configPath) require.NoError(t, err) data, err := os.ReadFile(configPath) require.NoError(t, err) assert.Contains(t, string(data), "conn_max_lifetime: 30m0s") } func configToDTO(c *Config) struct { Server struct { Port int `json:"port"` ReadTimeout string `json:"read_timeout"` WriteTimeout string `json:"write_timeout"` } Database struct { ConnMaxLifetime string `json:"conn_max_lifetime"` } } { var result struct { Server struct { Port int `json:"port"` ReadTimeout string `json:"read_timeout"` WriteTimeout string `json:"write_timeout"` } Database struct { ConnMaxLifetime string `json:"conn_max_lifetime"` } } result.Server.Port = c.Server.Port result.Server.ReadTimeout = c.Server.ReadTimeout.String() result.Server.WriteTimeout = c.Server.WriteTimeout.String() result.Database.ConnMaxLifetime = c.Database.ConnMaxLifetime.String() return result }