package static import ( "encoding/json" "testing" "github.com/alexei/tinyforge/internal/workload/plugin" ) func validCfg(extra map[string]any) json.RawMessage { m := map[string]any{"repo_owner": "o", "repo_name": "r"} for k, v := range extra { m[k] = v } b, _ := json.Marshal(m) return b } func TestValidate_Strategy(t *testing.T) { cases := []struct { strategy string wantErr bool }{ {"", false}, {"recreate", false}, {"blue-green", false}, {"rolling", true}, {"junk", true}, } for _, c := range cases { t.Run("strategy="+c.strategy, func(t *testing.T) { err := (&source{}).Validate(validCfg(map[string]any{"deploy_strategy": c.strategy})) if (err != nil) != c.wantErr { t.Fatalf("Validate(strategy=%q) err=%v, wantErr=%v", c.strategy, err, c.wantErr) } }) } } func TestEffectiveStrategy_DefaultAndDenoGate(t *testing.T) { if got := effectiveStrategy(Config{}); got != plugin.StrategyRecreate { t.Fatalf("empty strategy = %q, want recreate", got) } if got := effectiveStrategy(Config{DeployStrategy: plugin.StrategyBlueGreen}); got != plugin.StrategyBlueGreen { t.Fatalf("plain blue-green = %q, want blue-green", got) } // Storage-backed deno site requesting blue-green is forced to recreate to // avoid a concurrent-writer overlap on the shared /app/data volume. denoStorage := Config{DeployStrategy: plugin.StrategyBlueGreen, StorageEnabled: true, Mode: "deno"} if got := effectiveStrategy(denoStorage); got != plugin.StrategyRecreate { t.Fatalf("deno+storage blue-green = %q, want recreate (forced)", got) } // A deno site WITHOUT storage may use blue-green. denoNoStorage := Config{DeployStrategy: plugin.StrategyBlueGreen, Mode: "deno"} if got := effectiveStrategy(denoNoStorage); got != plugin.StrategyBlueGreen { t.Fatalf("deno (no storage) blue-green = %q, want blue-green", got) } }