Files
akvorado/common/httpserver/cache_test.go
Vincent Bernat bd37c1d553 common/httpserver: listen on an abstract Unix socket
And make healthcheck command use it by default. This makes the
healthcheck command works whatever port the user has configured for the
HTTP service.
2025-11-24 11:29:45 +01:00

176 lines
4.8 KiB
Go

// SPDX-FileCopyrightText: 2022 Free Mobile
// SPDX-License-Identifier: AGPL-3.0-only
package httpserver_test
import (
"context"
"net/http"
"testing"
"time"
"akvorado/common/daemon"
"akvorado/common/helpers"
"akvorado/common/httpserver"
"akvorado/common/reporter"
"github.com/gin-gonic/gin"
"github.com/go-redis/redis/v8"
)
func TestCacheByRequestPath(t *testing.T) {
r := reporter.NewMock(t)
h := httpserver.NewMock(t, r)
count := 0
h.GinRouter.GET("/api/v0/test",
h.CacheByRequestPath(time.Minute),
func(c *gin.Context) {
count++
c.JSON(http.StatusOK, gin.H{
"message": "ping",
"count": count,
})
})
// Check the HTTP server is running and answering metrics
helpers.TestHTTPEndpoints(t, h.LocalAddr(), helpers.HTTPEndpointCases{
{
Description: "not cached",
URL: "/api/v0/test",
JSONOutput: gin.H{"message": "ping", "count": 1},
}, {
Description: "cached",
URL: "/api/v0/test",
JSONOutput: gin.H{"message": "ping", "count": 1},
}, {
Description: "cached twice",
URL: "/api/v0/test",
JSONOutput: gin.H{"message": "ping", "count": 1},
},
})
gotMetrics := r.GetMetrics("akvorado_common_httpserver_", "requests_", "cache_")
expectedMetrics := map[string]string{
`cache_hit_total{method="GET",path="/api/v0/test"}`: "2",
`cache_miss_total{method="GET",path="/api/v0/test"}`: "1",
`requests_total{code="200",handler="/api/",method="get"}`: "3",
}
if diff := helpers.Diff(gotMetrics, expectedMetrics); diff != "" {
t.Fatalf("Metrics (-got, +want):\n%s", diff)
}
}
func TestCacheByRequestBody(t *testing.T) {
r := reporter.NewMock(t)
h := httpserver.NewMock(t, r)
count := 0
h.GinRouter.POST("/api/v0/test",
h.CacheByRequestBody(time.Minute),
func(c *gin.Context) {
count++
data, err := c.GetRawData()
if err != nil {
t.Fatalf("GetRawData() error:\n%+v", err)
}
c.JSON(http.StatusOK, gin.H{
"message": "ping",
"count": count,
"body": string(data),
})
})
// Check the HTTP server is running and answering metrics
helpers.TestHTTPEndpoints(t, h.LocalAddr(), helpers.HTTPEndpointCases{
{
Description: "not cached",
URL: "/api/v0/test",
JSONInput: gin.H{"hop": 1},
JSONOutput: gin.H{"message": "ping", "count": 1, "body": `{"hop":1}` + "\n"},
}, {
Description: "cached",
URL: "/api/v0/test",
JSONInput: gin.H{"hop": 1},
JSONOutput: gin.H{"message": "ping", "count": 1, "body": `{"hop":1}` + "\n"},
}, {
Description: "different body",
URL: "/api/v0/test",
JSONInput: gin.H{"hop": 2},
JSONOutput: gin.H{"message": "ping", "count": 2, "body": `{"hop":2}` + "\n"},
}, {
Description: "different body cached",
URL: "/api/v0/test",
JSONInput: gin.H{"hop": 2},
JSONOutput: gin.H{"message": "ping", "count": 2, "body": `{"hop":2}` + "\n"},
},
})
gotMetrics := r.GetMetrics("akvorado_common_httpserver_", "requests_", "cache_")
expectedMetrics := map[string]string{
`cache_hit_total{method="POST",path="/api/v0/test"}`: "2",
`cache_miss_total{method="POST",path="/api/v0/test"}`: "2",
`requests_total{code="200",handler="/api/",method="post"}`: "4",
}
if diff := helpers.Diff(gotMetrics, expectedMetrics); diff != "" {
t.Fatalf("Metrics (-got, +want):\n%s", diff)
}
}
func TestRedis(t *testing.T) {
server := helpers.CheckExternalService(t, "Redis",
[]string{"redis:6379", "127.0.0.1:6379"})
client := redis.NewClient(&redis.Options{
Addr: server,
DB: 10,
})
defer client.Close()
if err := client.FlushAll(context.Background()).Err(); err != nil {
t.Fatalf("FlushAll() error:\n%+v", err)
}
r := reporter.NewMock(t)
// HTTP with Redis
config := httpserver.DefaultConfiguration()
config.Listen = "127.0.0.1:0"
config.Cache.Config = httpserver.RedisCacheConfiguration{
Protocol: "tcp",
Server: server,
DB: 10,
}
h, err := httpserver.New(r, "cache-test", config, httpserver.Dependencies{Daemon: daemon.NewMock(t)})
if err != nil {
t.Fatalf("New() error:\n%+v", err)
}
helpers.StartStop(t, h)
count := 0
h.GinRouter.GET("/api/v0/test",
h.CacheByRequestPath(time.Minute),
func(c *gin.Context) {
count++
c.JSON(http.StatusOK, gin.H{
"message": "ping",
"count": count,
})
})
// Check the HTTP server is running and answering metrics
helpers.TestHTTPEndpoints(t, h.LocalAddr(), helpers.HTTPEndpointCases{
{
Description: "not cached",
URL: "/api/v0/test",
JSONOutput: gin.H{"message": "ping", "count": 1},
}, {
Description: "cached",
URL: "/api/v0/test",
JSONOutput: gin.H{"message": "ping", "count": 1},
},
})
if err := client.Get(context.Background(), "cache-/api/v0/test").Err(); err != nil {
t.Fatalf("GET(\"cache-/api/v0/test\") error:\n%+v", err)
}
}