mirror of
https://github.com/navidrome/navidrome.git
synced 2026-08-31 07:30:32 +00:00
test: tighten the tests added with the Go 1.27 bugfixes
Drop the testItem stub in favour of the package's own cacheKey, register the pprof test profile once at package scope, and replace the hand-rolled goroutine settle loop with Eventually. Also corrects a comment that credited a TestMain the scanner suite does not have.
This commit is contained in:
parent
6afa093710
commit
59923120e8
@ -13,6 +13,8 @@ import (
|
||||
. "github.com/onsi/gomega"
|
||||
)
|
||||
|
||||
var _ = pprof.NewProfile("nd-profiler-test")
|
||||
|
||||
var _ = Describe("profilerHandler", func() {
|
||||
// Mirrors how server.MountRouter mounts the handler.
|
||||
mount := func() http.Handler {
|
||||
@ -23,9 +25,6 @@ var _ = Describe("profilerHandler", func() {
|
||||
|
||||
BeforeEach(func() {
|
||||
DeferCleanup(configtest.SetupConfig())
|
||||
if pprof.Lookup("nd-profiler-test") == nil {
|
||||
pprof.NewProfile("nd-profiler-test")
|
||||
}
|
||||
})
|
||||
|
||||
DescribeTable("serves a named profile",
|
||||
@ -33,7 +32,7 @@ var _ = Describe("profilerHandler", func() {
|
||||
conf.Server.BasePath = basePath
|
||||
|
||||
w := httptest.NewRecorder()
|
||||
target := path.Join(basePath, "/debug/pprof/nd-profiler-test") + "?debug=1"
|
||||
target := basePath + "/debug/pprof/nd-profiler-test?debug=1"
|
||||
mount().ServeHTTP(w, httptest.NewRequest(http.MethodGet, target, nil))
|
||||
|
||||
Expect(w.Code).To(Equal(http.StatusOK))
|
||||
|
||||
@ -603,37 +603,33 @@ var _ = Describe("CacheService Integration", Ordered, func() {
|
||||
})
|
||||
|
||||
var _ = Describe("newCacheService", func() {
|
||||
// Background goroutines wind down late, so poll for two consecutive equal samples.
|
||||
settleGoroutines := func() int {
|
||||
prev := -1
|
||||
for range 100 {
|
||||
// The suite above leaves goroutines winding down, so settle before sampling.
|
||||
settledBaseline := func() int {
|
||||
var n int
|
||||
Eventually(func() int {
|
||||
runtime.GC()
|
||||
n := runtime.NumGoroutine()
|
||||
if n == prev {
|
||||
return n
|
||||
}
|
||||
prev = n
|
||||
time.Sleep(10 * time.Millisecond)
|
||||
}
|
||||
return prev
|
||||
prev := n
|
||||
n = runtime.NumGoroutine()
|
||||
return n - prev
|
||||
}).WithTimeout(10 * time.Second).WithPolling(20 * time.Millisecond).Should(BeZero())
|
||||
return n
|
||||
}
|
||||
|
||||
It("stops the janitor goroutine once the service is unreachable", func() {
|
||||
const numServices = 20
|
||||
const numServices = 5
|
||||
baseline := settledBaseline()
|
||||
|
||||
baseline := settleGoroutines()
|
||||
func() {
|
||||
services := make([]*cacheServiceImpl, 0, numServices)
|
||||
for i := range numServices {
|
||||
services = append(services, newCacheService(fmt.Sprintf("plugin_%d", i)))
|
||||
}
|
||||
Expect(runtime.NumGoroutine()).To(BeNumerically(">=", baseline+numServices),
|
||||
"expected one janitor goroutine per cache service")
|
||||
}()
|
||||
|
||||
services := make([]*cacheServiceImpl, 0, numServices)
|
||||
for i := range numServices {
|
||||
services = append(services, newCacheService(fmt.Sprintf("plugin_%d", i)))
|
||||
}
|
||||
Expect(runtime.NumGoroutine()).To(BeNumerically(">=", baseline+numServices),
|
||||
"expected one janitor goroutine per cache service")
|
||||
|
||||
services = nil
|
||||
Expect(services).To(BeNil())
|
||||
|
||||
Expect(settleGoroutines()).To(BeNumerically("<", baseline+numServices),
|
||||
"janitor goroutines leaked after the services became unreachable")
|
||||
Eventually(func() int { runtime.GC(); return runtime.NumGoroutine() }).
|
||||
WithTimeout(10*time.Second).WithPolling(20*time.Millisecond).
|
||||
Should(BeNumerically("<=", baseline), "janitor goroutines leaked")
|
||||
})
|
||||
})
|
||||
|
||||
@ -35,7 +35,7 @@ func BenchmarkScan(b *testing.B) {
|
||||
goleak.IgnoreTopFunction("github.com/rjeczalik/notify.(*recursiveTree).dispatch"),
|
||||
)
|
||||
|
||||
// Benchmarks run without the suite's TestMain, so the config defaults must be loaded here
|
||||
// go test -bench runs with -run=XXX, so TestScanner never loads the test config
|
||||
tests.Init(b, false)
|
||||
|
||||
tmpDir := b.TempDir()
|
||||
|
||||
@ -10,10 +10,6 @@ import (
|
||||
. "github.com/onsi/gomega"
|
||||
)
|
||||
|
||||
type testItem string
|
||||
|
||||
func (i testItem) Key() string { return string(i) }
|
||||
|
||||
type recordingBody struct {
|
||||
io.Reader
|
||||
closed *bool
|
||||
@ -53,7 +49,7 @@ var _ = Describe("serveImage", func() {
|
||||
It("closes the response body when the hosting service returns an error", func() {
|
||||
stubStatus(http.StatusNotFound)
|
||||
|
||||
_, err := (&Handler{}).serveImage(context.Background(), testItem("some-image.webp"))
|
||||
_, err := (&Handler{}).serveImage(context.Background(), cacheKey("some-image.webp"))
|
||||
|
||||
Expect(err).To(MatchError(ContainSubstring("unexpected status code")))
|
||||
Expect(closed).To(BeTrue(), "response body was left open")
|
||||
@ -62,7 +58,7 @@ var _ = Describe("serveImage", func() {
|
||||
It("hands the still-open body to the caller on success", func() {
|
||||
stubStatus(http.StatusOK)
|
||||
|
||||
reader, err := (&Handler{}).serveImage(context.Background(), testItem("some-image.webp"))
|
||||
reader, err := (&Handler{}).serveImage(context.Background(), cacheKey("some-image.webp"))
|
||||
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
Expect(closed).To(BeFalse(), "response body must stay open for the CachedStream wrapper")
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user