package config import "testing" func TestStoreOverlayKeepsBaseSeparate(t *testing.T) { base := Default() s := NewStore(base, "") if s.Base() != base || s.Get() != base { t.Fatal("without an overlay base and current are the same config") } extra := Group{Name: "from-cluster", Policy: "deny"} s.SetOverlay(func(b *Config) *Config { next := *b next.ACL.Groups = append(append([]Group(nil), b.ACL.Groups...), extra) return &next }) var seen *Config s.OnSwap(func(c *Config) { seen = c }) gen := s.Generation() s.Reapply() if got := s.Get().ACL.Groups; len(got) != 1 || got[0].Name != "from-cluster" { t.Fatalf("effective groups = %+v", got) } if len(s.Base().ACL.Groups) != 0 { t.Fatal("the overlay leaked into the base") } if seen != s.Get() || s.Generation() != gen+1 { t.Fatal("Reapply must run the swap hooks and bump the generation") } // A write (the API persisting a change) replaces the base; the overlay // is applied on top of it again. written := Default() written.ACL.Groups = []Group{{Name: "yaml", Policy: "allow"}} if err := s.Swap(written); err != nil { t.Fatal(err) } if got := s.Get().ACL.Groups; len(got) != 2 || got[0].Name != "yaml" || got[1].Name != "from-cluster" { t.Fatalf("after Swap = %+v", got) } if got := s.Base().ACL.Groups; len(got) != 1 { t.Fatalf("base after Swap = %+v", got) } }