Files
HeatGuard/internal/llm/llm_test.go
vikingowl 5e6696aa42 feat: add AI-powered actions endpoint and timeline annotations
Add LLM actions endpoint that generates hour-specific heat
management recommendations. Replace static action engine with
AI-driven approach. Add cool mode logic (ventilate/ac/overloaded),
indoor temperature tracking, and timeline legend with annotations.
2026-02-10 03:54:09 +01:00

126 lines
3.3 KiB
Go

package llm
import (
"context"
"encoding/json"
"net/http"
"net/http/httptest"
"testing"
)
func TestNoopProvider(t *testing.T) {
n := NewNoop()
if n.Name() != "none" {
t.Errorf("Name = %s, want none", n.Name())
}
s, err := n.Summarize(context.Background(), SummaryInput{})
if err != nil || s != "" {
t.Errorf("Summarize = (%q, %v), want empty", s, err)
}
r, err := n.RewriteAction(context.Background(), ActionInput{})
if err != nil || r != "" {
t.Errorf("RewriteAction = (%q, %v), want empty", r, err)
}
h, err := n.GenerateHeatPlan(context.Background(), HeatPlanInput{})
if err != nil || h != "" {
t.Errorf("GenerateHeatPlan = (%q, %v), want empty", h, err)
}
a, err := n.GenerateActions(context.Background(), ActionsInput{})
if err != nil || a != "" {
t.Errorf("GenerateActions = (%q, %v), want empty", a, err)
}
}
func TestAnthropicProvider_MockServer(t *testing.T) {
srv := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
if r.Header.Get("x-api-key") != "test-key" {
t.Error("missing api key header")
}
if r.Header.Get("anthropic-version") != "2023-06-01" {
t.Error("missing anthropic-version header")
}
json.NewEncoder(w).Encode(map[string]any{
"content": []map[string]string{
{"type": "text", "text": "- Bullet one\n- Bullet two\n- Bullet three"},
},
})
}))
defer srv.Close()
a := NewAnthropic("test-key", "test-model", srv.Client())
a.baseURL = srv.URL
result, err := a.Summarize(context.Background(), testSummaryInput())
if err != nil {
t.Fatalf("Summarize: %v", err)
}
if result == "" {
t.Error("empty result")
}
}
func TestAnthropicProvider_Error(t *testing.T) {
srv := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
json.NewEncoder(w).Encode(map[string]any{
"error": map[string]string{"message": "invalid api key"},
})
}))
defer srv.Close()
a := NewAnthropic("bad-key", "", srv.Client())
a.baseURL = srv.URL
_, err := a.Summarize(context.Background(), SummaryInput{})
if err == nil {
t.Error("expected error")
}
}
func TestOpenAIProvider_MockServer(t *testing.T) {
srv := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
if !containsBearer(r.Header.Get("Authorization")) {
t.Error("missing bearer token")
}
json.NewEncoder(w).Encode(map[string]any{
"choices": []map[string]any{
{"message": map[string]string{"content": "Test summary"}},
},
})
}))
defer srv.Close()
o := NewOpenAI("test-key", "test-model", srv.Client())
o.baseURL = srv.URL
result, err := o.Summarize(context.Background(), testSummaryInput())
if err != nil {
t.Fatalf("Summarize: %v", err)
}
if result != "Test summary" {
t.Errorf("result = %q, want 'Test summary'", result)
}
}
func TestOllamaProvider_MockServer(t *testing.T) {
srv := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
json.NewEncoder(w).Encode(map[string]any{
"message": map[string]string{"content": "Ollama summary"},
})
}))
defer srv.Close()
o := NewOllama("test-model", srv.URL, srv.Client())
result, err := o.Summarize(context.Background(), testSummaryInput())
if err != nil {
t.Fatalf("Summarize: %v", err)
}
if result != "Ollama summary" {
t.Errorf("result = %q, want 'Ollama summary'", result)
}
}
func containsBearer(s string) bool {
return len(s) > 7 && s[:7] == "Bearer "
}