feat(api): dedupe registered spec groups
Prevent duplicate RouteGroup registrations from appearing multiple times in CLI-generated OpenAPI output. This keeps spec generation stable when packages register the same group more than once during init or tests. Co-Authored-By: Virgil <virgil@lethean.io>
This commit is contained in:
parent
69beb451b5
commit
0144244ccd
2 changed files with 77 additions and 0 deletions
|
|
@ -23,6 +23,9 @@ func RegisterSpecGroups(groups ...RouteGroup) {
|
|||
if group == nil {
|
||||
continue
|
||||
}
|
||||
if specRegistryContains(group) {
|
||||
continue
|
||||
}
|
||||
specRegistry.groups = append(specRegistry.groups, group)
|
||||
}
|
||||
}
|
||||
|
|
@ -37,3 +40,30 @@ func RegisteredSpecGroups() []RouteGroup {
|
|||
copy(out, specRegistry.groups)
|
||||
return out
|
||||
}
|
||||
|
||||
// ResetSpecGroups clears the package-level spec registry.
|
||||
// It is primarily intended for tests that need to isolate global state.
|
||||
func ResetSpecGroups() {
|
||||
specRegistry.mu.Lock()
|
||||
defer specRegistry.mu.Unlock()
|
||||
|
||||
specRegistry.groups = nil
|
||||
}
|
||||
|
||||
func specRegistryContains(group RouteGroup) bool {
|
||||
key := specGroupKey(group)
|
||||
for _, existing := range specRegistry.groups {
|
||||
if specGroupKey(existing) == key {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func specGroupKey(group RouteGroup) string {
|
||||
if group == nil {
|
||||
return ""
|
||||
}
|
||||
|
||||
return group.Name() + "\x00" + group.BasePath()
|
||||
}
|
||||
|
|
|
|||
47
spec_registry_test.go
Normal file
47
spec_registry_test.go
Normal file
|
|
@ -0,0 +1,47 @@
|
|||
// SPDX-License-Identifier: EUPL-1.2
|
||||
|
||||
package api_test
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
|
||||
api "dappco.re/go/core/api"
|
||||
)
|
||||
|
||||
type specRegistryStubGroup struct {
|
||||
name string
|
||||
basePath string
|
||||
}
|
||||
|
||||
func (g *specRegistryStubGroup) Name() string { return g.name }
|
||||
func (g *specRegistryStubGroup) BasePath() string { return g.basePath }
|
||||
func (g *specRegistryStubGroup) RegisterRoutes(rg *gin.RouterGroup) {}
|
||||
|
||||
func TestRegisterSpecGroups_Good_DeduplicatesByIdentity(t *testing.T) {
|
||||
snapshot := api.RegisteredSpecGroups()
|
||||
api.ResetSpecGroups()
|
||||
t.Cleanup(func() {
|
||||
api.ResetSpecGroups()
|
||||
api.RegisterSpecGroups(snapshot...)
|
||||
})
|
||||
|
||||
first := &specRegistryStubGroup{name: "alpha", basePath: "/alpha"}
|
||||
second := &specRegistryStubGroup{name: "alpha", basePath: "/alpha"}
|
||||
third := &specRegistryStubGroup{name: "beta", basePath: "/beta"}
|
||||
|
||||
api.RegisterSpecGroups(nil, first, second, third, first)
|
||||
|
||||
groups := api.RegisteredSpecGroups()
|
||||
if len(groups) != 2 {
|
||||
t.Fatalf("expected 2 unique groups, got %d", len(groups))
|
||||
}
|
||||
|
||||
if groups[0].Name() != "alpha" || groups[0].BasePath() != "/alpha" {
|
||||
t.Fatalf("expected first group to be alpha at /alpha, got %s at %s", groups[0].Name(), groups[0].BasePath())
|
||||
}
|
||||
if groups[1].Name() != "beta" || groups[1].BasePath() != "/beta" {
|
||||
t.Fatalf("expected second group to be beta at /beta, got %s at %s", groups[1].Name(), groups[1].BasePath())
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Reference in a new issue