Files
gitea/build/openapi3gen/enumscan_test.go
T
silverwind 8abda62312 test: consolidate Go tests (#39962)
Consolidate all Go tests. Coverage is identical to before. Go tests are
around 5% faster while being 7% smaller. No non-test code is touched.
2026-10-24 13:48:19 +00:00

219 lines
4.8 KiB
Go

// Copyright 2026 The Gitea Authors. All rights reserved.
// SPDX-License-Identifier: MIT
package openapi3gen
import (
"os"
"path/filepath"
"slices"
"strings"
"testing"
)
func single(got map[string][]string, key string) string {
v := got[key]
if len(v) != 1 {
return ""
}
return v[0]
}
func TestEnumKey_sortsAndJoins(t *testing.T) {
key := EnumKey([]any{"b", "a", "c"})
if key != "a|b|c" {
t.Fatalf("EnumKey = %q, want %q", key, "a|b|c")
}
}
func TestEnumKey_handlesNonStringValues(t *testing.T) {
key := EnumKey([]any{2, 1, 3})
if key != "1|2|3" {
t.Fatalf("EnumKey = %q, want %q", key, "1|2|3")
}
}
func TestScanSwaggerEnumTypes(t *testing.T) {
scan := func(t *testing.T, filename, src string) (map[string][]string, error) {
dir := t.TempDir()
if err := os.WriteFile(filepath.Join(dir, filename), []byte(src), 0o644); err != nil {
t.Fatal(err)
}
return ScanSwaggerEnumTypes([]string{dir})
}
t.Run("basic", func(t *testing.T) {
got, err := scan(t, "color.go", `package fixture
// Color is a primary color.
// swagger:enum Color
type Color string
const (
ColorRed Color = "red"
ColorGreen Color = "green"
ColorBlue Color = "blue"
)
`)
if err != nil {
t.Fatalf("ScanSwaggerEnumTypes: %v", err)
}
wantKey := EnumKey([]any{"red", "green", "blue"})
if single(got, wantKey) != "Color" {
t.Fatalf("map[%q] = %q, want %q", wantKey, got[wantKey], "Color")
}
})
t.Run("orphanAnnotation", func(t *testing.T) {
_, err := scan(t, "typo.go", `package fixture
// swagger:enum Sttype
type StateType string
const (
StateOpen StateType = "open"
)
`)
if err == nil {
t.Fatal("expected error for annotation referencing a non-matching type name")
}
if !strings.Contains(err.Error(), "Sttype") {
t.Fatalf("error %q should mention the typo'd name Sttype", err.Error())
}
})
t.Run("collision", func(t *testing.T) {
got, err := scan(t, "dup.go", `package fixture
// swagger:enum Alpha
type Alpha string
const (
AlphaX Alpha = "x"
AlphaY Alpha = "y"
)
// swagger:enum Beta
type Beta string
const (
BetaX Beta = "x"
BetaY Beta = "y"
)
`)
if err != nil {
t.Fatalf("ScanSwaggerEnumTypes: %v", err)
}
key := EnumKey([]any{"x", "y"})
names := got[key]
if !slices.Equal(names, []string{"Alpha", "Beta"}) {
t.Fatalf("map[%q] = %v, want [Alpha Beta]", key, names)
}
})
t.Run("parseFailure", func(t *testing.T) {
_, err := scan(t, "bad.go", "package fixture\nfunc Foo() {")
if err == nil {
t.Fatal("expected parse error, got nil")
}
})
t.Run("annotationWithoutConsts", func(t *testing.T) {
_, err := scan(t, "lonely.go", `package fixture
// swagger:enum Lonely
type Lonely string
`)
if err == nil {
t.Fatal("expected error for annotation without consts")
}
if !strings.Contains(err.Error(), "Lonely") {
t.Fatalf("error %q should mention Lonely", err.Error())
}
})
t.Run("constsBeforeType", func(t *testing.T) {
got, err := scan(t, "shade.go", `package fixture
const (
ShadeDark Shade = "dark"
ShadeLight Shade = "light"
)
// swagger:enum Shade
type Shade string
`)
if err != nil {
t.Fatalf("ScanSwaggerEnumTypes: %v", err)
}
wantKey := EnumKey([]any{"dark", "light"})
if single(got, wantKey) != "Shade" {
t.Fatalf("map[%q] = %q, want %q", wantKey, got[wantKey], "Shade")
}
})
t.Run("groupedTypeDecl", func(t *testing.T) {
got, err := scan(t, "grouped.go", `package fixture
type (
// swagger:enum Color
Color string
// swagger:enum Shade
Shade string
)
const (
ColorRed Color = "red"
ColorBlue Color = "blue"
)
const (
ShadeDark Shade = "dark"
ShadeLight Shade = "light"
)
`)
if err != nil {
t.Fatalf("ScanSwaggerEnumTypes: %v", err)
}
colorKey := EnumKey([]any{"red", "blue"})
shadeKey := EnumKey([]any{"dark", "light"})
if single(got, colorKey) != "Color" {
t.Fatalf("Color: map[%q] = %q, want %q", colorKey, got[colorKey], "Color")
}
if single(got, shadeKey) != "Shade" {
t.Fatalf("Shade: map[%q] = %q, want %q", shadeKey, got[shadeKey], "Shade")
}
})
}
func TestScanSwaggerEnumTypes_constsAndTypeInDifferentFiles(t *testing.T) {
dir := t.TempDir()
// Name ordering: `a_consts.go` < `b_type.go`, so readdir returns consts first.
// Old single-pass scanner would miss the values; two-pass must not.
constsSrc := `package fixture
const (
HueA Hue = "a"
HueB Hue = "b"
)
`
typeSrc := `package fixture
// swagger:enum Hue
type Hue string
`
if err := os.WriteFile(filepath.Join(dir, "a_consts.go"), []byte(constsSrc), 0o644); err != nil {
t.Fatal(err)
}
if err := os.WriteFile(filepath.Join(dir, "b_type.go"), []byte(typeSrc), 0o644); err != nil {
t.Fatal(err)
}
got, err := ScanSwaggerEnumTypes([]string{dir})
if err != nil {
t.Fatalf("ScanSwaggerEnumTypes: %v", err)
}
wantKey := EnumKey([]any{"a", "b"})
if single(got, wantKey) != "Hue" {
t.Fatalf("map[%q] = %q, want %q", wantKey, got[wantKey], "Hue")
}
}