Files
LocalAI/pkg/model/initializers_load_logging_test.go
T
Ettore Di Giacinto 7b66df6651 test: fix the three data races that made -race runs noisy
None was introduced by this branch and all three are in test code, which is
what made them survive: every suite passed on every run and only the race
detector said otherwise. A known-failing -race run is worse than a noisy one,
because a real race raised by production code lands in the same report and is
read as one of these.

galleryop: gatedModelManager guarded the recorded names and not the gate
channel itself. A spec frees the parked worker by closing the gate and
installing a fresh one, on the spec goroutine, while the worker goroutine reads
the field to park on it. The channel is now read and replaced under the same
mutex, and cleanup closes idempotently.

pkg/model: two specs swapped xlog's package logger to capture output and
swapped it back on cleanup. xlog.SetLogger writes an unsynchronised global, so
the restore raced with the backend process watcher, which logs while a process
is stopping; the captured bytes.Buffer was written by that goroutine and read
by an Eventually at the same time. SetLogger is now called once for the whole
test binary, from init, before a goroutine exists to race with, and a spec
swaps the DESTINATION under a mutex through a routing slog.Handler. Per-spec
level filtering is preserved deliberately: one of these specs asserts that a
debug emission is filtered OUT and would pass vacuously against a handler that
recorded everything.

openai: fakeTransport appended to its event and audio logs from the response
and turn coordinators' goroutines while a spec ranged over them. Both are
behind a mutex and are read through snapshot accessors; the fields are renamed
so a raw read from another spec file does not compile.

Assisted-by: Claude Opus 5 [claude-code]
Signed-off-by: Ettore Di Giacinto <mudler@localai.io>
2026-09-06 05:24:18 +00:00

95 lines
3.3 KiB
Go

package model
import (
"log/slog"
pb "github.com/mudler/LocalAI/pkg/grpc/proto"
"github.com/mudler/LocalAI/pkg/system"
. "github.com/onsi/ginkgo/v2"
. "github.com/onsi/gomega"
)
// backendLoader is not a synonym for "a model is being loaded". In distributed
// mode Load() deliberately bypasses the local cache and calls backendLoader on
// every inference request so SmartRouter can re-pick a replica per request, so
// the function runs at request rate against an already-resident model. Emitting
// the load banner unconditionally made ordinary embedding traffic (~5 req/s)
// look like a retry storm in the INFO log and sent an engineer chasing a
// non-existent hot loop during an unrelated production investigation. INFO must
// mark a genuine cold load only; the per-call trace belongs at DEBUG.
var _ = Describe("backendLoader load logging", func() {
var (
ml *ModelLoader
captured *syncBuffer
)
BeforeEach(func() {
systemState, err := system.GetSystemState(system.WithModelPath(GinkgoT().TempDir()))
Expect(err).ToNot(HaveOccurred())
ml = NewModelLoader(systemState)
// Capture at info level so a debug-level emission is filtered out: the
// assertions then fail on severity, not merely on wording.
captured = captureLogs(slog.LevelInfo)
})
AfterEach(stopCapturingLogs)
Context("when the model is already resident", func() {
BeforeEach(func() {
resident := NewModel("resident-model", "127.0.0.1:65535", nil)
// Skip the gRPC health probe so the resident model survives the
// lookup without a live backend behind the address.
resident.MarkHealthy()
ml.mu.Lock()
ml.store.Set("resident-model", resident)
ml.mu.Unlock()
})
It("does not announce a load at info level", func() {
_, err := ml.backendLoader(
WithModelID("resident-model"),
WithModel("resident-model"),
WithBackendString("llama-cpp"),
WithLoadGRPCLoadModelOpts(&pb.ModelOptions{ContextSize: 4096}),
)
Expect(err).ToNot(HaveOccurred())
Expect(captured.String()).ToNot(ContainSubstring("BackendLoader starting"),
"a request served by an already-resident model must not look like a cold load")
})
It("does not repeat the effective runtime tuning banner at info level", func() {
_, err := ml.backendLoader(
WithModelID("resident-model"),
WithModel("resident-model"),
WithBackendString("llama-cpp"),
WithLoadGRPCLoadModelOpts(&pb.ModelOptions{ContextSize: 4096}),
)
Expect(err).ToNot(HaveOccurred())
Expect(captured.String()).ToNot(ContainSubstring("effective runtime tuning"),
"the tuning banner documents what a load will run with, so it belongs to a load")
})
})
Context("when the model is not resident", func() {
It("still announces the cold load at info level", func() {
// The load itself fails (no such backend is installed); what is
// pinned here is that the banner is emitted before that, so
// suppressing the warm case does not silence real loads.
_, err := ml.backendLoader(
WithModelID("cold-model"),
WithModel("cold-model"),
WithBackendString("definitely-not-an-installed-backend"),
WithLoadGRPCLoadModelOpts(&pb.ModelOptions{ContextSize: 4096}),
)
Expect(err).To(HaveOccurred())
Expect(captured.String()).To(ContainSubstring("BackendLoader starting"))
Expect(captured.String()).To(ContainSubstring("effective runtime tuning"))
})
})
})