Files
capsule/internal/cache/jsonpaths_test.go
T
cc4fb45d70 feat: upstream enterprise preview (#1841)
feat: upstream enterprise preview

---------

Signed-off-by: Oliver Baehler <oliver@sudo-i.net>
Co-authored-by: CorentinPtrl <pitrel.corentin@gmail.com>
2026-05-28 00:58:58 +02:00

186 lines
4.2 KiB
Go

// Copyright 2020-2026 Project Capsule Authors
// SPDX-License-Identifier: Apache-2.0
package cache
import (
"sync"
"sync/atomic"
. "github.com/onsi/ginkgo/v2"
. "github.com/onsi/gomega"
)
var _ = Describe("JSONPathCache", func() {
var c *JSONPathCache
BeforeEach(func() {
c = NewJSONPathCache()
})
It("returns false when path is missing", func() {
value, ok := c.Get(".spec.missing")
Expect(ok).To(BeFalse())
Expect(value).To(BeNil())
})
It("compiles and stores a JSONPath", func() {
compiled, err := c.GetOrCompile(".spec.containers[*].resources.requests.cpu")
Expect(err).NotTo(HaveOccurred())
Expect(compiled).NotTo(BeNil())
Expect(c.Stats()).To(Equal(1))
cached, ok := c.Get(".spec.containers[*].resources.requests.cpu")
Expect(ok).To(BeTrue())
Expect(cached).To(BeIdenticalTo(compiled))
})
It("returns the cached instance on repeated GetOrCompile calls", func() {
first, err := c.GetOrCompile(".spec.resources.requests.storage")
Expect(err).NotTo(HaveOccurred())
second, err := c.GetOrCompile(".spec.resources.requests.storage")
Expect(err).NotTo(HaveOccurred())
Expect(second).To(BeIdenticalTo(first))
Expect(c.Stats()).To(Equal(1))
})
It("does not store invalid JSONPath expressions", func() {
compiled, err := c.GetOrCompile(".spec.containers[?(")
Expect(err).To(HaveOccurred())
Expect(compiled).To(BeNil())
Expect(c.Stats()).To(Equal(0))
_, ok := c.Get(".spec.containers[?(")
Expect(ok).To(BeFalse())
})
It("deletes an existing path", func() {
_, err := c.GetOrCompile(".spec.replicas")
Expect(err).NotTo(HaveOccurred())
Expect(c.Delete(".spec.replicas")).To(BeTrue())
Expect(c.Delete(".spec.replicas")).To(BeFalse())
_, ok := c.Get(".spec.replicas")
Expect(ok).To(BeFalse())
Expect(c.Stats()).To(Equal(0))
})
It("deletes many paths and ignores missing or empty expressions", func() {
_, err := c.GetOrCompile(".spec.a")
Expect(err).NotTo(HaveOccurred())
_, err = c.GetOrCompile(".spec.b")
Expect(err).NotTo(HaveOccurred())
_, err = c.GetOrCompile(".spec.c")
Expect(err).NotTo(HaveOccurred())
deleted := c.DeleteMany(".spec.a", "", ".spec.missing", ".spec.c")
Expect(deleted).To(Equal(2))
Expect(c.Stats()).To(Equal(1))
_, ok := c.Get(".spec.a")
Expect(ok).To(BeFalse())
_, ok = c.Get(".spec.b")
Expect(ok).To(BeTrue())
_, ok = c.Get(".spec.c")
Expect(ok).To(BeFalse())
})
It("resets all compiled paths", func() {
_, err := c.GetOrCompile(".spec.a")
Expect(err).NotTo(HaveOccurred())
_, err = c.GetOrCompile(".spec.b")
Expect(err).NotTo(HaveOccurred())
Expect(c.Stats()).To(Equal(2))
c.Reset()
Expect(c.Stats()).To(Equal(0))
_, ok := c.Get(".spec.a")
Expect(ok).To(BeFalse())
})
It("prunes inactive paths", func() {
_, err := c.GetOrCompile(".spec.a")
Expect(err).NotTo(HaveOccurred())
_, err = c.GetOrCompile(".spec.b")
Expect(err).NotTo(HaveOccurred())
_, err = c.GetOrCompile(".spec.c")
Expect(err).NotTo(HaveOccurred())
pruned := c.PruneActive(map[string]struct{}{
".spec.a": {},
".spec.c": {},
})
Expect(pruned).To(Equal(1))
Expect(c.Stats()).To(Equal(2))
_, ok := c.Get(".spec.a")
Expect(ok).To(BeTrue())
_, ok = c.Get(".spec.b")
Expect(ok).To(BeFalse())
_, ok = c.Get(".spec.c")
Expect(ok).To(BeTrue())
})
It("prunes all paths when active set is empty", func() {
_, err := c.GetOrCompile(".spec.a")
Expect(err).NotTo(HaveOccurred())
_, err = c.GetOrCompile(".spec.b")
Expect(err).NotTo(HaveOccurred())
Expect(c.PruneActive(map[string]struct{}{})).To(Equal(2))
Expect(c.Stats()).To(Equal(0))
})
It("is safe under concurrent GetOrCompile calls for the same path", func() {
const workers = 32
var successes atomic.Int32
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
compiled, err := c.GetOrCompile(".spec.containers[*].resources.requests.cpu")
Expect(err).NotTo(HaveOccurred())
Expect(compiled).NotTo(BeNil())
successes.Add(1)
}()
}
close(start)
wg.Wait()
Expect(successes.Load()).To(Equal(int32(workers)))
Expect(c.Stats()).To(Equal(1))
})
})