package appconfig import ( "bytes" "context" "errors" "os" "testing" "github.com/carlosframework/platform/internal/release" ) // Review Focus 1: an app that has never had config gets none from setting // the defaults, so no box sees a config change. func TestSwapPolicyDefaultsWriteNothing(t *testing.T) { ctx := context.Background() s := release.NewDirStore(t.TempDir()) got, err := SetSwapPolicy(ctx, s, "bab", "shop", SwapOverlap, 1) if err != nil { t.Fatal(err) } if got != (SwapPolicy{Swap: SwapOverlap, Concurrency: 1}) { t.Fatalf("policy = %+v, want overlap/1", got) } if _, _, err := s.Get(ctx, Key("bab", "shop")); !errors.Is(err, os.ErrNotExist) { t.Fatalf("setting the defaults created config.json: %v", err) } if _, _, err := s.Get(ctx, GenKey("bab", "shop")); !errors.Is(err, os.ErrNotExist) { t.Fatalf("setting the defaults touched the config generation: %v", err) } } func TestSwapPolicyHoldKeepsTheRestOfTheBundle(t *testing.T) { ctx := context.Background() s := release.NewDirStore(t.TempDir()) if err := SetEnv(ctx, s, "bab", "shop", map[string]string{"A": "1"}); err != nil { t.Fatal(err) } if err := SetExecDelivery(ctx, s, "bab", "shop", ExecDeliveryFile); err != nil { t.Fatal(err) } got, err := SetSwapPolicy(ctx, s, "bab", "shop", SwapHold, 3) if err != nil || got != (SwapPolicy{Swap: SwapHold, Concurrency: 3}) { t.Fatalf("policy = %+v, %v; want hold/3", got, err) } m, err := Get(ctx, s, "bab", "shop") if err != nil { t.Fatal(err) } if m.Swap != SwapHold || m.SwapConcurrency != 3 || m.Vars["A"].Value != "1" || m.ExecDelivery != ExecDeliveryFile { t.Fatalf("manifest after set = %+v", m) } if _, _, err := s.Get(ctx, GenKey("bab", "shop")); err != nil { t.Fatalf("a real change must touch the config generation: %v", err) } if _, err := SetSwapPolicy(ctx, s, "bab", "shop", SwapOverlap, 1); err != nil { t.Fatal(err) } raw, _, err := s.Get(ctx, Key("bab", "shop")) if err != nil { t.Fatal(err) } if bytes.Contains(raw, []byte(`"swap`)) { t.Fatalf("defaults still stored: %s", raw) } } func TestSwapPolicyLeavesTheUnnamedHalf(t *testing.T) { ctx := context.Background() s := release.NewDirStore(t.TempDir()) if _, err := SetSwapPolicy(ctx, s, "bab", "shop", SwapHold, 0); err != nil { t.Fatal(err) } got, err := SetSwapPolicy(ctx, s, "bab", "shop", "", 2) if err != nil || got != (SwapPolicy{Swap: SwapHold, Concurrency: 2}) { t.Fatalf("policy = %+v, %v; want hold kept and 2 set", got, err) } } func TestSwapPolicyRefusesBadValues(t *testing.T) { ctx := context.Background() s := release.NewDirStore(t.TempDir()) if _, err := SetSwapPolicy(ctx, s, "bab", "shop", "fast", 0); err == nil { t.Error("swap fast was accepted") } if _, err := SetSwapPolicy(ctx, s, "bab", "shop", "", -1); err == nil { t.Error("concurrency -1 was accepted") } if _, err := SetSwapPolicy(ctx, s, "bab", "Shop!", SwapHold, 0); err == nil { t.Error("an invalid app name was accepted") } if _, _, err := s.Get(ctx, Key("bab", "shop")); !errors.Is(err, os.ErrNotExist) { t.Fatalf("a refused call wrote config.json: %v", err) } } func TestPolicyOfFailsTowardHold(t *testing.T) { if got := PolicyOf(nil); got != (SwapPolicy{Swap: SwapOverlap, Concurrency: 1}) { t.Errorf("PolicyOf(nil) = %+v", got) } if got := PolicyOf(&Manifest{Swap: "fast"}); got.Swap != SwapHold { t.Errorf("an unknown stored mode reads as %q, want hold", got.Swap) } if got := PolicyOf(&Manifest{SwapConcurrency: -2}); got.Concurrency != 1 { t.Errorf("a negative stored concurrency reads as %d, want 1", got.Concurrency) } }