Files
glpi-neuroforge-mega/platform/neuroforge/internal/provider/runtime_test.go
T
groot d18405ed2e
ci / test (services/knowledge) (push) Successful in 47s
ci / test (services/agent) (push) Successful in 55s
ci / test (platform/neuroforge) (push) Successful in 56s
ci / docker-build (push) Failing after 1m10s
ci / test (services/control) (push) Successful in 1m26s
release-tag / release-image (push) Successful in 6m43s
update-1.6.2
2026-09-09 12:55:35 +02:00

159 lines
4.4 KiB
Go

package provider
import (
"context"
"encoding/json"
"net/http"
"net/http/httptest"
"testing"
"time"
"neuroforge/internal/core"
"neuroforge/internal/store"
)
func TestRouterHasNoGlobalInferenceTimeout(t *testing.T) {
s, err := store.New(t.TempDir())
if err != nil {
t.Fatal(err)
}
defer s.Close()
r := NewRouter(s)
if r.http.Timeout != 0 {
t.Fatalf("global http client timeout=%v, want 0", r.http.Timeout)
}
tr, ok := r.http.Transport.(*http.Transport)
if !ok {
t.Fatalf("transport type %T", r.http.Transport)
}
if tr.ResponseHeaderTimeout != 0 {
t.Fatalf("response header timeout=%v, want 0 for long non-streaming inference", tr.ResponseHeaderTimeout)
}
}
func TestOllamaRuntimeOptionsAreSent(t *testing.T) {
var got map[string]any
fake := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
if r.URL.Path != "/api/chat" {
http.NotFound(w, r)
return
}
if err := json.NewDecoder(r.Body).Decode(&got); err != nil {
t.Fatal(err)
}
_ = json.NewEncoder(w).Encode(map[string]any{
"message": map[string]any{"content": "ok"},
"prompt_eval_count": 4,
"eval_count": 3,
})
}))
defer fake.Close()
s, err := store.New(t.TempDir())
if err != nil {
t.Fatal(err)
}
defer s.Close()
cfg := s.Config()
cfg.Routing.ChatProvider = "ollama"
cfg.Routing.ChatNodeID = "local"
cfg.Ollama = []core.OllamaServer{{
ID: "local", Name: "Local", BaseURL: fake.URL, ChatModel: "qwen-test", EmbeddingModel: "embed-test",
Weight: 1, Enabled: true, RequestTimeoutSeconds: 0, NumCtx: 8192, NumPredict: 512,
Think: "low", ChatKeepAlive: "30m", EmbeddingKeepAlive: "5m",
}}
if err := s.UpdateConfig(cfg); err != nil {
t.Fatal(err)
}
r := NewRouter(s)
if _, err := r.Chat(context.Background(), "ollama", "", "", "hello", 1400); err != nil {
t.Fatal(err)
}
if got["keep_alive"] != "30m" || got["think"] != "low" {
t.Fatalf("runtime body=%#v", got)
}
opts, ok := got["options"].(map[string]any)
if !ok {
t.Fatalf("options missing: %#v", got)
}
if opts["num_ctx"] != float64(8192) || opts["num_predict"] != float64(512) {
t.Fatalf("options=%#v", opts)
}
}
func TestOllamaExplicitRequestTimeoutStillWorks(t *testing.T) {
fake := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
time.Sleep(1200 * time.Millisecond)
_ = json.NewEncoder(w).Encode(map[string]any{"message": map[string]any{"content": "late"}})
}))
defer fake.Close()
s, err := store.New(t.TempDir())
if err != nil {
t.Fatal(err)
}
defer s.Close()
cfg := s.Config()
cfg.Ollama[0].BaseURL = fake.URL
cfg.Ollama[0].RequestTimeoutSeconds = 1
if err := s.UpdateConfig(cfg); err != nil {
t.Fatal(err)
}
r := NewRouter(s)
start := time.Now()
_, err = r.ChatOn(context.Background(), "ollama", "", "local", "", "hello", 32)
if err == nil {
t.Fatal("expected configured timeout")
}
if time.Since(start) > 2*time.Second {
t.Fatalf("configured timeout was not enforced promptly: %v", time.Since(start))
}
}
func TestOllamaBearerTokenIsSentToChatAndHealth(t *testing.T) {
const token = "ollama-secret"
var chatAuth, tagsAuth string
fake := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
switch r.URL.Path {
case "/api/chat":
chatAuth = r.Header.Get("Authorization")
_ = json.NewEncoder(w).Encode(map[string]any{"message": map[string]any{"content": "ok"}})
case "/api/tags":
tagsAuth = r.Header.Get("Authorization")
_ = json.NewEncoder(w).Encode(map[string]any{"models": []map[string]any{{"name": "chat"}, {"name": "embed"}}})
default:
http.NotFound(w, r)
}
}))
defer fake.Close()
s, err := store.New(t.TempDir())
if err != nil {
t.Fatal(err)
}
defer s.Close()
cfg := s.Config()
cfg.Ollama = []core.OllamaServer{{ID: "secure", Name: "secure", BaseURL: fake.URL, ChatModel: "chat", EmbeddingModel: "embed", Weight: 1, Enabled: true}}
cfg.Routing.ChatProvider = "ollama"
if err := s.UpdateConfig(cfg); err != nil {
t.Fatal(err)
}
sec := s.Secrets()
sec.OllamaAPIKey = token
if err := s.UpdateSecrets(sec); err != nil {
t.Fatal(err)
}
r := NewRouter(s)
if _, err := r.Chat(context.Background(), "ollama", "chat", "", "hello", 32); err != nil {
t.Fatal(err)
}
_ = r.Health(context.Background())
if chatAuth != "Bearer "+token {
t.Fatalf("chat authorization=%q", chatAuth)
}
if tagsAuth != "Bearer "+token {
t.Fatalf("tags authorization=%q", tagsAuth)
}
}