Files
any-hub/tests/integration/module_diagnostics_test.go
2025-11-15 21:15:12 +08:00

155 lines
4.1 KiB
Go

package integration
import (
"encoding/json"
"io"
"net/http"
"net/http/httptest"
"testing"
"time"
"github.com/gofiber/fiber/v3"
"github.com/sirupsen/logrus"
"github.com/any-hub/any-hub/internal/config"
"github.com/any-hub/any-hub/internal/hubmodule"
"github.com/any-hub/any-hub/internal/server"
"github.com/any-hub/any-hub/internal/server/routes"
)
func TestModuleDiagnosticsEndpoints(t *testing.T) {
const moduleKey = "diagnostics-test"
_ = hubmodule.Register(hubmodule.ModuleMetadata{
Key: moduleKey,
Description: "diagnostics test module",
MigrationState: hubmodule.MigrationStateBeta,
SupportedProtocols: []string{
"npm",
},
})
cfg := &config.Config{
Global: config.GlobalConfig{
ListenPort: 6200,
CacheTTL: config.Duration(30 * time.Minute),
},
Hubs: []config.HubConfig{
{
Name: "legacy-hub",
Domain: "legacy.local",
Type: "docker",
Upstream: "https://registry-1.docker.io",
},
{
Name: "modern-hub",
Domain: "modern.local",
Type: "npm",
Upstream: "https://registry.npmjs.org",
Module: moduleKey,
Rollout: "dual",
},
},
}
registry, err := server.NewHubRegistry(cfg)
if err != nil {
t.Fatalf("failed to build registry: %v", err)
}
logger := logrus.New()
logger.SetOutput(io.Discard)
app := mustNewApp(t, cfg.Global.ListenPort, logger, registry, server.ProxyHandlerFunc(func(c fiber.Ctx, _ *server.HubRoute) error {
return c.SendStatus(fiber.StatusNoContent)
}))
routes.RegisterModuleRoutes(app, registry)
t.Run("list modules and hubs", func(t *testing.T) {
resp := doRequest(t, app, "GET", "/-/modules")
if resp.StatusCode != fiber.StatusOK {
t.Fatalf("expected 200, got %d", resp.StatusCode)
}
var payload struct {
Modules []map[string]any `json:"modules"`
Hubs []struct {
HubName string `json:"hub_name"`
ModuleKey string `json:"module_key"`
Rollout string `json:"rollout_flag"`
Domain string `json:"domain"`
Port int `json:"port"`
} `json:"hubs"`
}
body, _ := io.ReadAll(resp.Body)
resp.Body.Close()
if err := json.Unmarshal(body, &payload); err != nil {
t.Fatalf("failed to decode response: %v\nbody: %s", err, string(body))
}
if len(payload.Modules) == 0 {
t.Fatalf("expected module metadata entries")
}
found := false
for _, module := range payload.Modules {
if module["key"] == moduleKey {
found = true
break
}
}
if !found {
t.Fatalf("expected module %s in diagnostics payload", moduleKey)
}
if len(payload.Hubs) != 2 {
t.Fatalf("expected 2 hubs, got %d", len(payload.Hubs))
}
for _, hub := range payload.Hubs {
switch hub.HubName {
case "legacy-hub":
if hub.ModuleKey != hubmodule.DefaultModuleKey() {
t.Fatalf("legacy hub should expose legacy module, got %s", hub.ModuleKey)
}
case "modern-hub":
if hub.ModuleKey != moduleKey {
t.Fatalf("modern hub should expose %s, got %s", moduleKey, hub.ModuleKey)
}
if hub.Rollout != "dual" {
t.Fatalf("modern hub rollout flag should be dual, got %s", hub.Rollout)
}
default:
t.Fatalf("unexpected hub %s", hub.HubName)
}
}
})
t.Run("inspect module by key", func(t *testing.T) {
resp := doRequest(t, app, "GET", "/-/modules/"+moduleKey)
if resp.StatusCode != fiber.StatusOK {
t.Fatalf("expected 200, got %d", resp.StatusCode)
}
var module map[string]any
body, _ := io.ReadAll(resp.Body)
resp.Body.Close()
if err := json.Unmarshal(body, &module); err != nil {
t.Fatalf("module inspect decode failed: %v", err)
}
if module["key"] != moduleKey {
t.Fatalf("expected module key %s, got %v", moduleKey, module["key"])
}
})
t.Run("unknown module returns 404", func(t *testing.T) {
resp := doRequest(t, app, "GET", "/-/modules/missing-module")
if resp.StatusCode != fiber.StatusNotFound {
t.Fatalf("expected 404, got %d", resp.StatusCode)
}
})
}
func doRequest(t *testing.T, app *fiber.App, method, url string) *http.Response {
t.Helper()
req := httptest.NewRequest(method, url, nil)
resp, err := app.Test(req)
if err != nil {
t.Fatalf("request %s %s failed: %v", method, url, err)
}
return resp
}