108 lines
4.0 KiB
Go
108 lines
4.0 KiB
Go
package apigen
|
|
|
|
import (
|
|
"encoding/json"
|
|
"fmt"
|
|
apierrors "git.yuntuo.hk/k2safe/go-omni/errors"
|
|
"strings"
|
|
"testing"
|
|
)
|
|
|
|
func TestSharedErrorDocumentReferences(t *testing.T) {
|
|
source := `@app(defaultResponse: Common)
|
|
response Common(codeType:int32;successCode:0;errorCode:9999;messageField:msg;dataMode:always)
|
|
service demo {
|
|
`
|
|
for i := 0; i < 16; i++ {
|
|
kind := "string"
|
|
if i%2 == 0 {
|
|
kind = "int64"
|
|
}
|
|
source += fmt.Sprintf("@handler list%d\nget /list%d returns ([]%s)\n", i, i, kind)
|
|
}
|
|
source += "}\n"
|
|
spec, err := parseText(t, source)
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
catalog := apierrors.Catalog{DefaultStatus: 400, Definitions: map[string]apierrors.Definition{}}
|
|
for i := 0; i < 80; i++ {
|
|
status := 400
|
|
if i%2 == 0 {
|
|
status = 200
|
|
}
|
|
catalog.Definitions[fmt.Sprintf("ERROR_%d", i)] = apierrors.Definition{Status: status, Code: 400000 + i, Message: strings.Repeat("说明", 40) + "{label}不能超过{max}个字符", Params: []apierrors.Parameter{{Name: "label", Type: "string", Example: "企业名称"}, {Name: "max", Type: "int", Example: 100}}}
|
|
}
|
|
spec.DocumentCatalog = &catalog
|
|
compiled, err := Compile(spec)
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
var raw map[string]any
|
|
if err = json.Unmarshal(compiled.Document, &raw); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
components := raw["components"].(map[string]any)
|
|
for _, kind := range []string{"responses", "examples"} {
|
|
if len(components[kind].(map[string]any)) == 0 {
|
|
t.Fatal("missing shared", kind)
|
|
}
|
|
}
|
|
expanded := document(t, compiled)
|
|
for i := 0; i < 16; i++ {
|
|
responses := operation(t, expanded, fmt.Sprintf("/list%d", i), "get")["responses"].(map[string]any)
|
|
for _, status := range []string{"200", "400"} {
|
|
media := responses[status].(map[string]any)["content"].(map[string]any)["application/json"].(map[string]any)
|
|
if len(media["examples"].(map[string]any)) != 40 {
|
|
t.Fatal("examples lost")
|
|
}
|
|
if status == "200" {
|
|
choices := media["schema"].(map[string]any)["anyOf"].([]any)
|
|
if len(choices) != 2 || choices[0].(map[string]any)["properties"].(map[string]any)["data"].(map[string]any)["type"] != "array" {
|
|
t.Fatal("200 success shape lost")
|
|
}
|
|
}
|
|
for _, example := range media["examples"].(map[string]any) {
|
|
value := example.(map[string]any)["value"].(map[string]any)
|
|
if _, ok := value["data"]; !ok || value["data"] != nil || !strings.Contains(value["msg"].(string), "企业名称不能超过100个字符") {
|
|
t.Fatal(value)
|
|
}
|
|
}
|
|
}
|
|
}
|
|
expandedBytes, _ := json.MarshalIndent(expanded, "", " ")
|
|
if len(compiled.Document)*5 > len(expandedBytes) {
|
|
t.Fatalf("poor dedup: %d vs %d", len(compiled.Document), len(expandedBytes))
|
|
}
|
|
again, err := Compile(spec)
|
|
if err != nil || string(again.Document) != string(compiled.Document) {
|
|
t.Fatal("non-deterministic document", err)
|
|
}
|
|
before, _ := json.Marshal(raw)
|
|
compactDocument(raw)
|
|
data, _ := json.Marshal(raw)
|
|
if string(data) != string(before) {
|
|
t.Fatal("compaction not idempotent")
|
|
}
|
|
}
|
|
|
|
func TestSharedSchemasAndLiteralExampleReference(t *testing.T) {
|
|
doc := map[string]any{"components": map[string]any{}, "paths": map[string]any{}}
|
|
paths := doc["paths"].(map[string]any)
|
|
for _, name := range []string{"first", "second", "third"} {
|
|
schema := map[string]any{"type": "object", "description": strings.Repeat("schema description ", 40)}
|
|
example := map[string]any{"summary": strings.Repeat("example ", 50), "value": map[string]any{"$ref": "literal business field"}}
|
|
paths["/"+name] = map[string]any{"get": map[string]any{"responses": map[string]any{"200": map[string]any{"description": name, "content": map[string]any{"application/json": map[string]any{"schema": schema, "examples": map[string]any{"same": example}}}}}}}
|
|
}
|
|
compactDocument(doc)
|
|
components := doc["components"].(map[string]any)
|
|
if len(components["schemas"].(map[string]any)) != 1 {
|
|
t.Fatal("schema not shared")
|
|
}
|
|
for _, example := range components["examples"].(map[string]any) {
|
|
if example.(map[string]any)["value"].(map[string]any)["$ref"] != "literal business field" {
|
|
t.Fatal("payload reference interpreted")
|
|
}
|
|
}
|
|
}
|