test(router): закрепить пространства имён API тестом регистрации маршрутов
Ошибка в регистрации маршрутов проявляется паникой при старте сервиса, а не ответом с кодом: конфликт с wildcard фронтенда или дублирующая регистрация обнаружились бы только на живом сервере. Смена namespace относится ровно к этому классу изменений.
This commit is contained in:
@@ -0,0 +1,107 @@
|
||||
package router
|
||||
|
||||
import (
|
||||
"strings"
|
||||
"testing"
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
"hy2xs-admin/model/constant"
|
||||
)
|
||||
|
||||
// Регистрация маршрутов — единственное место, где ошибка проявляется паникой
|
||||
// при старте сервиса, а не ответом с кодом. Смена пространства имён API как
|
||||
// раз относится к таким изменениям: конфликт с wildcard-маршрутом фронтенда
|
||||
// или дублирующая регистрация обнаружились бы только на живом сервере.
|
||||
func buildRoutes(t *testing.T) gin.RoutesInfo {
|
||||
t.Helper()
|
||||
gin.SetMode(gin.TestMode)
|
||||
|
||||
engine := gin.New()
|
||||
defer func() {
|
||||
if r := recover(); r != nil {
|
||||
t.Fatalf("сборка маршрутов паникует: %v", r)
|
||||
}
|
||||
}()
|
||||
Router(engine)
|
||||
return engine.Routes()
|
||||
}
|
||||
|
||||
func TestRouterRegistersMachineAuthUnderInternalNamespace(t *testing.T) {
|
||||
routes := buildRoutes(t)
|
||||
|
||||
found := false
|
||||
for _, route := range routes {
|
||||
if route.Method == "POST" && route.Path == constant.HysteriaMachineAuthPath {
|
||||
found = true
|
||||
}
|
||||
}
|
||||
if !found {
|
||||
t.Fatalf("machine-auth endpoint не зарегистрирован на %s", constant.HysteriaMachineAuthPath)
|
||||
}
|
||||
}
|
||||
|
||||
func TestRouterKeepsAdminAndAuthUnderApiNamespace(t *testing.T) {
|
||||
routes := buildRoutes(t)
|
||||
|
||||
expected := []string{
|
||||
constant.AdminAPIBase + "/auth/login",
|
||||
constant.AdminAPIBase + "/peers",
|
||||
constant.AdminAPIBase + "/config/listConfig",
|
||||
constant.AdminAPIBase + "/peer-import",
|
||||
constant.AdminAPIBase + "/peer-export",
|
||||
}
|
||||
present := make(map[string]bool, len(routes))
|
||||
for _, route := range routes {
|
||||
present[route.Path] = true
|
||||
}
|
||||
for _, path := range expected {
|
||||
if !present[path] {
|
||||
t.Errorf("маршрут %s не зарегистрирован", path)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Старое пространство имён — часть runtime-контракта, а не внутреннее имя:
|
||||
// его возвращение сломало бы конфиг Hysteria на уже установленных серверах.
|
||||
func TestRouterHasNoLegacyNamespace(t *testing.T) {
|
||||
for _, route := range buildRoutes(t) {
|
||||
if strings.HasPrefix(route.Path, "/hui") {
|
||||
t.Errorf("вернулось legacy-пространство имён: %s %s", route.Method, route.Path)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Маршруты, операциями которых продукт не владеет, удалены, а не оставлены
|
||||
// отвечающими «feature disabled».
|
||||
func TestRouterHasNoRemovedRoutes(t *testing.T) {
|
||||
removed := []string{
|
||||
"exportConfig",
|
||||
"importConfig",
|
||||
"updateHysteria2Config",
|
||||
"importHysteria2Config",
|
||||
"hysteria2ChangeVersion",
|
||||
"listRelease",
|
||||
"restartServer",
|
||||
"uploadCertFile",
|
||||
"hysteria2AcmePath",
|
||||
}
|
||||
for _, route := range buildRoutes(t) {
|
||||
for _, dead := range removed {
|
||||
if strings.Contains(route.Path, dead) {
|
||||
t.Errorf("удалённый маршрут вернулся: %s %s", route.Method, route.Path)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestRouterExposesHealthz(t *testing.T) {
|
||||
found := false
|
||||
for _, route := range buildRoutes(t) {
|
||||
if route.Method == "GET" && route.Path == "/healthz" {
|
||||
found = true
|
||||
}
|
||||
}
|
||||
if !found {
|
||||
t.Fatal("/healthz не зарегистрирован")
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user