mirror of
https://github.com/projectcapsule/capsule.git
synced 2026-08-19 20:46:42 +00:00
feat: upstream enterprise preview --------- Signed-off-by: Oliver Baehler <oliver@sudo-i.net> Co-authored-by: CorentinPtrl <pitrel.corentin@gmail.com>
236 lines
5.5 KiB
Go
236 lines
5.5 KiB
Go
// Copyright 2020-2026 Project Capsule Authors
|
|
// SPDX-License-Identifier: Apache-2.0
|
|
|
|
package cache
|
|
|
|
import (
|
|
"errors"
|
|
"sync"
|
|
"sync/atomic"
|
|
|
|
. "github.com/onsi/ginkgo/v2"
|
|
. "github.com/onsi/gomega"
|
|
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
|
|
|
capsulev1beta2 "github.com/projectcapsule/capsule/api/v1beta2"
|
|
)
|
|
|
|
var _ = Describe("CompiledTargetsCache", func() {
|
|
var c *CompiledTargetsCache[string]
|
|
|
|
target := func(kind string) CompiledTarget {
|
|
return CompiledTarget{
|
|
CustomQuotaStatusTarget: capsulev1beta2.CustomQuotaStatusTarget{
|
|
GroupVersionKind: metav1.GroupVersionKind{
|
|
Group: "",
|
|
Version: "v1",
|
|
Kind: kind,
|
|
},
|
|
},
|
|
}
|
|
}
|
|
|
|
BeforeEach(func() {
|
|
c = NewCompiledTargetsCache[string]()
|
|
})
|
|
|
|
It("returns false when key is missing", func() {
|
|
value, ok := c.Get("missing")
|
|
|
|
Expect(ok).To(BeFalse())
|
|
Expect(value).To(BeNil())
|
|
})
|
|
|
|
It("sets and gets values", func() {
|
|
c.Set("quota-a", []CompiledTarget{target("Pod"), target("Service")})
|
|
|
|
value, ok := c.Get("quota-a")
|
|
|
|
Expect(ok).To(BeTrue())
|
|
Expect(value).To(HaveLen(2))
|
|
Expect(value[0].Kind).To(Equal("Pod"))
|
|
Expect(value[1].Kind).To(Equal("Service"))
|
|
Expect(c.Stats()).To(Equal(1))
|
|
})
|
|
|
|
It("returns a copy from Get", func() {
|
|
c.Set("quota-a", []CompiledTarget{target("Pod")})
|
|
|
|
value, ok := c.Get("quota-a")
|
|
Expect(ok).To(BeTrue())
|
|
|
|
value[0].Kind = "Mutated"
|
|
value = append(value, target("Service"))
|
|
|
|
again, ok := c.Get("quota-a")
|
|
Expect(ok).To(BeTrue())
|
|
Expect(again).To(HaveLen(1))
|
|
Expect(again[0].Kind).To(Equal("Pod"))
|
|
})
|
|
|
|
It("stores a copy from Set", func() {
|
|
original := []CompiledTarget{target("Pod")}
|
|
|
|
c.Set("quota-a", original)
|
|
|
|
original[0].Kind = "Mutated"
|
|
original = append(original, target("Service"))
|
|
|
|
value, ok := c.Get("quota-a")
|
|
Expect(ok).To(BeTrue())
|
|
Expect(value).To(HaveLen(1))
|
|
Expect(value[0].Kind).To(Equal("Pod"))
|
|
})
|
|
|
|
It("builds missing values with GetOrBuild", func() {
|
|
var calls atomic.Int32
|
|
|
|
value, err := c.GetOrBuild("quota-a", func() ([]CompiledTarget, error) {
|
|
calls.Add(1)
|
|
return []CompiledTarget{target("Pod")}, nil
|
|
})
|
|
|
|
Expect(err).NotTo(HaveOccurred())
|
|
Expect(value).To(HaveLen(1))
|
|
Expect(value[0].Kind).To(Equal("Pod"))
|
|
Expect(calls.Load()).To(Equal(int32(1)))
|
|
|
|
cached, ok := c.Get("quota-a")
|
|
Expect(ok).To(BeTrue())
|
|
Expect(cached).To(HaveLen(1))
|
|
})
|
|
|
|
It("does not call build when key already exists", func() {
|
|
c.Set("quota-a", []CompiledTarget{target("Pod")})
|
|
|
|
value, err := c.GetOrBuild("quota-a", func() ([]CompiledTarget, error) {
|
|
return nil, errors.New("should not be called")
|
|
})
|
|
|
|
Expect(err).NotTo(HaveOccurred())
|
|
Expect(value).To(HaveLen(1))
|
|
Expect(value[0].Kind).To(Equal("Pod"))
|
|
})
|
|
|
|
It("does not store value when build fails", func() {
|
|
expectedErr := errors.New("compile failed")
|
|
|
|
value, err := c.GetOrBuild("quota-a", func() ([]CompiledTarget, error) {
|
|
return nil, expectedErr
|
|
})
|
|
|
|
Expect(err).To(MatchError(expectedErr))
|
|
Expect(value).To(BeNil())
|
|
|
|
_, ok := c.Get("quota-a")
|
|
Expect(ok).To(BeFalse())
|
|
Expect(c.Stats()).To(Equal(0))
|
|
})
|
|
|
|
It("returns a copy from GetOrBuild", func() {
|
|
value, err := c.GetOrBuild("quota-a", func() ([]CompiledTarget, error) {
|
|
return []CompiledTarget{target("Pod")}, nil
|
|
})
|
|
Expect(err).NotTo(HaveOccurred())
|
|
|
|
value[0].Kind = "Mutated"
|
|
value = append(value, target("Service"))
|
|
|
|
again, err := c.GetOrBuild("quota-a", func() ([]CompiledTarget, error) {
|
|
return []CompiledTarget{target("ShouldNotBuild")}, nil
|
|
})
|
|
Expect(err).NotTo(HaveOccurred())
|
|
Expect(again).To(HaveLen(1))
|
|
Expect(again[0].Kind).To(Equal("Pod"))
|
|
})
|
|
|
|
It("deletes existing values", func() {
|
|
c.Set("quota-a", []CompiledTarget{target("Pod")})
|
|
|
|
Expect(c.Delete("quota-a")).To(BeTrue())
|
|
Expect(c.Delete("quota-a")).To(BeFalse())
|
|
|
|
_, ok := c.Get("quota-a")
|
|
Expect(ok).To(BeFalse())
|
|
Expect(c.Stats()).To(Equal(0))
|
|
})
|
|
|
|
It("resets all values", func() {
|
|
c.Set("quota-a", []CompiledTarget{target("Pod")})
|
|
c.Set("quota-b", []CompiledTarget{target("Service")})
|
|
|
|
Expect(c.Stats()).To(Equal(2))
|
|
|
|
c.Reset()
|
|
|
|
Expect(c.Stats()).To(Equal(0))
|
|
|
|
_, ok := c.Get("quota-a")
|
|
Expect(ok).To(BeFalse())
|
|
})
|
|
|
|
It("prunes inactive keys", func() {
|
|
c.Set("quota-a", []CompiledTarget{target("Pod")})
|
|
c.Set("quota-b", []CompiledTarget{target("Service")})
|
|
c.Set("quota-c", []CompiledTarget{target("PersistentVolumeClaim")})
|
|
|
|
pruned := c.PruneActive(map[string]struct{}{
|
|
"quota-a": {},
|
|
"quota-c": {},
|
|
})
|
|
|
|
Expect(pruned).To(Equal(1))
|
|
Expect(c.Stats()).To(Equal(2))
|
|
|
|
_, ok := c.Get("quota-a")
|
|
Expect(ok).To(BeTrue())
|
|
|
|
_, ok = c.Get("quota-b")
|
|
Expect(ok).To(BeFalse())
|
|
|
|
_, ok = c.Get("quota-c")
|
|
Expect(ok).To(BeTrue())
|
|
})
|
|
|
|
It("prunes all keys when active set is empty", func() {
|
|
c.Set("quota-a", []CompiledTarget{target("Pod")})
|
|
c.Set("quota-b", []CompiledTarget{target("Service")})
|
|
|
|
Expect(c.PruneActive(map[string]struct{}{})).To(Equal(2))
|
|
Expect(c.Stats()).To(Equal(0))
|
|
})
|
|
|
|
It("is safe under concurrent GetOrBuild calls for the same key", func() {
|
|
var calls atomic.Int32
|
|
const workers = 32
|
|
|
|
start := make(chan struct{})
|
|
var wg sync.WaitGroup
|
|
wg.Add(workers)
|
|
|
|
for i := 0; i < workers; i++ {
|
|
go func() {
|
|
defer GinkgoRecover()
|
|
defer wg.Done()
|
|
|
|
<-start
|
|
|
|
value, err := c.GetOrBuild("quota-a", func() ([]CompiledTarget, error) {
|
|
calls.Add(1)
|
|
return []CompiledTarget{target("Pod")}, nil
|
|
})
|
|
|
|
Expect(err).NotTo(HaveOccurred())
|
|
Expect(value).To(HaveLen(1))
|
|
Expect(value[0].Kind).To(Equal("Pod"))
|
|
}()
|
|
}
|
|
|
|
close(start)
|
|
wg.Wait()
|
|
|
|
Expect(calls.Load()).To(Equal(int32(1)))
|
|
Expect(c.Stats()).To(Equal(1))
|
|
})
|
|
})
|