Files
Containr/app/backend/internal/api/scaling_test.go
T
2026-04-10 12:02:36 +02:00

146 lines
4.1 KiB
Go

package api
import (
"bytes"
"encoding/json"
"net/http"
"net/http/httptest"
"testing"
"containr/internal/deployment"
"containr/internal/metrics"
"containr/internal/scaling"
"github.com/gin-gonic/gin"
)
func setupScalingTestRouter(t *testing.T) *gin.Engine {
t.Helper()
scheduler := deployment.NewScheduler()
if err := scheduler.RegisterNode(&deployment.Node{
ID: "node-test-1",
Name: "node-test-1",
Address: "127.0.0.1",
Status: "ready",
Capacity: deployment.ResourceCapacity{
CPU: 4,
Memory: 4 * 1024 * 1024 * 1024,
Storage: 100 * 1024 * 1024 * 1024,
Network: 1000,
},
}); err != nil {
t.Fatalf("failed to register test node: %v", err)
}
metricsStorage := metrics.NewInMemoryMetricsStorage()
metricsCollector := metrics.NewMetricsCollector(scheduler, metricsStorage)
autoScaler := scaling.NewAutoScaler(scheduler, metricsCollector)
if err := autoScaler.SetScalingPolicy(&scaling.ScalingPolicy{
ServiceID: "service-1",
MinReplicas: 1,
MaxReplicas: 10,
Enabled: true,
}); err != nil {
t.Fatalf("failed to set scaling policy: %v", err)
}
gin.SetMode(gin.TestMode)
router := gin.New()
handler := NewScalingHandler(autoScaler)
handler.RegisterRoutes(router.Group("/api/v1"))
return router
}
func TestScalingHistoryReturnsHistoryPayload(t *testing.T) {
router := setupScalingTestRouter(t)
req := httptest.NewRequest(http.MethodGet, "/api/v1/scaling/services/service-1/history", nil)
rec := httptest.NewRecorder()
router.ServeHTTP(rec, req)
if rec.Code != http.StatusOK {
t.Fatalf("expected status %d, got %d", http.StatusOK, rec.Code)
}
var body map[string]any
if err := json.Unmarshal(rec.Body.Bytes(), &body); err != nil {
t.Fatalf("failed to decode response: %v", err)
}
if body["service_id"] != "service-1" {
t.Fatalf("expected service_id service-1, got %v", body["service_id"])
}
if body["count"] != float64(0) {
t.Fatalf("expected count 0, got %v", body["count"])
}
}
func TestManualScaleUpdatesServiceState(t *testing.T) {
router := setupScalingTestRouter(t)
payload := []byte(`{"replicas":3,"reason":"ops override"}`)
req := httptest.NewRequest(http.MethodPost, "/api/v1/scaling/services/service-1/scale", bytes.NewReader(payload))
req.Header.Set("Content-Type", "application/json")
rec := httptest.NewRecorder()
router.ServeHTTP(rec, req)
if rec.Code != http.StatusOK {
t.Fatalf("expected status %d, got %d", http.StatusOK, rec.Code)
}
var body map[string]any
if err := json.Unmarshal(rec.Body.Bytes(), &body); err != nil {
t.Fatalf("failed to decode response: %v", err)
}
event, ok := body["event"].(map[string]any)
if !ok {
t.Fatalf("expected event payload, got %v", body["event"])
}
if event["action"] != "manual_scale_up" {
t.Fatalf("expected action manual_scale_up, got %v", event["action"])
}
state, ok := body["state"].(map[string]any)
if !ok {
t.Fatalf("expected state payload, got %v", body["state"])
}
if state["CurrentReplicas"] != float64(3) {
t.Fatalf("expected current replicas 3, got %v", state["CurrentReplicas"])
}
}
func TestScalingEventsReturnsRecentEvents(t *testing.T) {
router := setupScalingTestRouter(t)
scalePayload := []byte(`{"replicas":2,"reason":"ops override"}`)
scaleReq := httptest.NewRequest(http.MethodPost, "/api/v1/scaling/services/service-1/scale", bytes.NewReader(scalePayload))
scaleReq.Header.Set("Content-Type", "application/json")
scaleRec := httptest.NewRecorder()
router.ServeHTTP(scaleRec, scaleReq)
if scaleRec.Code != http.StatusOK {
t.Fatalf("expected status %d, got %d", http.StatusOK, scaleRec.Code)
}
req := httptest.NewRequest(http.MethodGet, "/api/v1/scaling/events?limit=5", nil)
rec := httptest.NewRecorder()
router.ServeHTTP(rec, req)
if rec.Code != http.StatusOK {
t.Fatalf("expected status %d, got %d", http.StatusOK, rec.Code)
}
var body map[string]any
if err := json.Unmarshal(rec.Body.Bytes(), &body); err != nil {
t.Fatalf("failed to decode response: %v", err)
}
if body["count"] != float64(1) {
t.Fatalf("expected count 1, got %v", body["count"])
}
events, ok := body["events"].([]any)
if !ok || len(events) != 1 {
t.Fatalf("expected one event, got %v", body["events"])
}
}