Files
ez-api/internal/api/apikey_stats_handler_test.go
zenfun 1a2cc5b798 feat(api): add API key stats flush and summary endpoints
Introduce internal endpoint for flushing accumulated APIKey statistics
from data plane to control plane database, updating both individual
API keys and their parent provider groups with request counts and
success/failure rates.

Add admin endpoint to retrieve aggregated API key statistics summary
across all provider groups, including total requests, success/failure
counts, and calculated rates.
2025-12-30 00:11:52 +08:00

69 lines
1.7 KiB
Go

package api
import (
"encoding/json"
"math"
"net/http"
"net/http/httptest"
"testing"
"github.com/ez-api/ez-api/internal/model"
"github.com/gin-gonic/gin"
"gorm.io/driver/sqlite"
"gorm.io/gorm"
)
func TestAdminHandler_GetAPIKeyStatsSummary(t *testing.T) {
gin.SetMode(gin.TestMode)
db, err := gorm.Open(sqlite.Open("file::memory:?cache=shared"), &gorm.Config{})
if err != nil {
t.Fatalf("open sqlite: %v", err)
}
if err := db.AutoMigrate(&model.APIKey{}); err != nil {
t.Fatalf("migrate: %v", err)
}
if err := db.Create(&model.APIKey{
GroupID: 1,
APIKey: "k1",
TotalRequests: 10,
SuccessRequests: 7,
FailureRequests: 3,
}).Error; err != nil {
t.Fatalf("create key1: %v", err)
}
if err := db.Create(&model.APIKey{
GroupID: 1,
APIKey: "k2",
TotalRequests: 5,
SuccessRequests: 5,
FailureRequests: 0,
}).Error; err != nil {
t.Fatalf("create key2: %v", err)
}
handler := &AdminHandler{db: db}
r := gin.New()
r.GET("/admin/apikey-stats/summary", handler.GetAPIKeyStatsSummary)
req := httptest.NewRequest(http.MethodGet, "/admin/apikey-stats/summary", nil)
rec := httptest.NewRecorder()
r.ServeHTTP(rec, req)
if rec.Code != http.StatusOK {
t.Fatalf("unexpected status: got=%d body=%s", rec.Code, rec.Body.String())
}
var resp APIKeyStatsSummaryResponse
if err := json.Unmarshal(rec.Body.Bytes(), &resp); err != nil {
t.Fatalf("decode response: %v", err)
}
if resp.TotalRequests != 15 || resp.SuccessRequests != 12 || resp.FailureRequests != 3 {
t.Fatalf("totals mismatch: %+v", resp)
}
if math.Abs(resp.SuccessRate-0.8) > 1e-6 || math.Abs(resp.FailureRate-0.2) > 1e-6 {
t.Fatalf("rates mismatch: success=%f failure=%f", resp.SuccessRate, resp.FailureRate)
}
}