package main import ( "os" "path/filepath" "strings" "testing" "git.mchus.pro/mchus/quoteforge/internal/config" ) func TestMigrateConfigFileToRuntimeShapeDropsDeprecatedSections(t *testing.T) { t.Helper() dir := t.TempDir() path := filepath.Join(dir, "config.yaml") legacy := `server: host: "0.0.0.0" port: 9191 database: host: "legacy-db" port: 3306 name: "RFQ_LOG" user: "old" password: "REDACTED_TEST_PASSWORD" pricing: default_method: "median" logging: level: "debug" format: "text" output: "stdout" ` if err := os.WriteFile(path, []byte(legacy), 0644); err != nil { t.Fatalf("write legacy config: %v", err) } cfg, err := config.Load(path) if err != nil { t.Fatalf("load legacy config: %v", err) } setConfigDefaults(cfg) cfg.Server.Host, _, err = normalizeLoopbackServerHost(cfg.Server.Host) if err != nil { t.Fatalf("normalize server host: %v", err) } if err := migrateConfigFileToRuntimeShape(path, cfg); err != nil { t.Fatalf("migrate config: %v", err) } got, err := os.ReadFile(path) if err != nil { t.Fatalf("read migrated config: %v", err) } text := string(got) if strings.Contains(text, "database:") { t.Fatalf("migrated config still contains deprecated database section:\n%s", text) } if strings.Contains(text, "pricing:") { t.Fatalf("migrated config still contains deprecated pricing section:\n%s", text) } if !strings.Contains(text, "server:") || !strings.Contains(text, "logging:") { t.Fatalf("migrated config missing required sections:\n%s", text) } if !strings.Contains(text, "port: 9191") { t.Fatalf("migrated config did not preserve server port:\n%s", text) } if !strings.Contains(text, "host: 127.0.0.1") { t.Fatalf("migrated config did not normalize server host:\n%s", text) } if !strings.Contains(text, "level: debug") { t.Fatalf("migrated config did not preserve logging level:\n%s", text) } } func TestNormalizeLoopbackServerHost(t *testing.T) { t.Parallel() cases := []struct { host string want string wantChanged bool wantErr bool }{ {host: "127.0.0.1", want: "127.0.0.1", wantChanged: false, wantErr: false}, {host: "localhost", want: "127.0.0.1", wantChanged: true, wantErr: false}, {host: "::1", want: "127.0.0.1", wantChanged: true, wantErr: false}, {host: "0.0.0.0", want: "127.0.0.1", wantChanged: true, wantErr: false}, {host: "192.168.1.10", want: "127.0.0.1", wantChanged: true, wantErr: false}, } for _, tc := range cases { got, changed, err := normalizeLoopbackServerHost(tc.host) if tc.wantErr && err == nil { t.Fatalf("expected error for host %q", tc.host) } if !tc.wantErr && err != nil { t.Fatalf("unexpected error for host %q: %v", tc.host, err) } if got != tc.want { t.Fatalf("unexpected normalized host for %q: got %q want %q", tc.host, got, tc.want) } if changed != tc.wantChanged { t.Fatalf("unexpected changed flag for %q: got %t want %t", tc.host, changed, tc.wantChanged) } } }