blob: a2d2f126f764072fd4aae38432929bcaa0d7d66e [file] [log] [blame]
package swagger
import (
"encoding/xml"
"net"
"reflect"
"testing"
"time"
)
type YesNo bool
func (y YesNo) MarshalJSON() ([]byte, error) {
if y {
return []byte("yes"), nil
}
return []byte("no"), nil
}
// clear && go test -v -test.run TestRef_Issue190 ...swagger
func TestRef_Issue190(t *testing.T) {
type User struct {
items []string
}
testJsonFromStruct(t, User{}, `{
"swagger.User": {
"id": "swagger.User",
"required": [
"items"
],
"properties": {
"items": {
"type": "array",
"items": {
"type": "string"
}
}
}
}
}`)
}
func TestWithoutAdditionalFormat(t *testing.T) {
type mytime struct {
time.Time
}
type usemytime struct {
t mytime
}
testJsonFromStruct(t, usemytime{}, `{
"swagger.usemytime": {
"id": "swagger.usemytime",
"required": [
"t"
],
"properties": {
"t": {
"type": "string"
}
}
}
}`)
}
func TestWithAdditionalFormat(t *testing.T) {
type mytime struct {
time.Time
}
type usemytime struct {
t mytime
}
testJsonFromStructWithConfig(t, usemytime{}, `{
"swagger.usemytime": {
"id": "swagger.usemytime",
"required": [
"t"
],
"properties": {
"t": {
"type": "string",
"format": "date-time"
}
}
}
}`, &Config{
SchemaFormatHandler: func(typeName string) string {
switch typeName {
case "swagger.mytime":
return "date-time"
}
return ""
},
})
}
// clear && go test -v -test.run TestCustomMarshaller_Issue96 ...swagger
func TestCustomMarshaller_Issue96(t *testing.T) {
type Vote struct {
What YesNo
}
testJsonFromStruct(t, Vote{}, `{
"swagger.Vote": {
"id": "swagger.Vote",
"required": [
"What"
],
"properties": {
"What": {
"type": "string"
}
}
}
}`)
}
// clear && go test -v -test.run TestPrimitiveTypes ...swagger
func TestPrimitiveTypes(t *testing.T) {
type Prims struct {
f float64
t time.Time
}
testJsonFromStruct(t, Prims{}, `{
"swagger.Prims": {
"id": "swagger.Prims",
"required": [
"f",
"t"
],
"properties": {
"f": {
"type": "number",
"format": "double"
},
"t": {
"type": "string",
"format": "date-time"
}
}
}
}`)
}
// clear && go test -v -test.run TestPrimitivePtrTypes ...swagger
func TestPrimitivePtrTypes(t *testing.T) {
type Prims struct {
f *float64
t *time.Time
b *bool
s *string
i *int
}
testJsonFromStruct(t, Prims{}, `{
"swagger.Prims": {
"id": "swagger.Prims",
"required": [
"f",
"t",
"b",
"s",
"i"
],
"properties": {
"b": {
"type": "boolean"
},
"f": {
"type": "number",
"format": "double"
},
"i": {
"type": "integer",
"format": "int32"
},
"s": {
"type": "string"
},
"t": {
"type": "string",
"format": "date-time"
}
}
}
}`)
}
// clear && go test -v -test.run TestS1 ...swagger
func TestS1(t *testing.T) {
type S1 struct {
Id string
}
testJsonFromStruct(t, S1{}, `{
"swagger.S1": {
"id": "swagger.S1",
"required": [
"Id"
],
"properties": {
"Id": {
"type": "string"
}
}
}
}`)
}
// clear && go test -v -test.run TestS2 ...swagger
func TestS2(t *testing.T) {
type S2 struct {
Ids []string
}
testJsonFromStruct(t, S2{}, `{
"swagger.S2": {
"id": "swagger.S2",
"required": [
"Ids"
],
"properties": {
"Ids": {
"type": "array",
"items": {
"type": "string"
}
}
}
}
}`)
}
// clear && go test -v -test.run TestS3 ...swagger
func TestS3(t *testing.T) {
type NestedS3 struct {
Id string
}
type S3 struct {
Nested NestedS3
}
testJsonFromStruct(t, S3{}, `{
"swagger.NestedS3": {
"id": "swagger.NestedS3",
"required": [
"Id"
],
"properties": {
"Id": {
"type": "string"
}
}
},
"swagger.S3": {
"id": "swagger.S3",
"required": [
"Nested"
],
"properties": {
"Nested": {
"$ref": "swagger.NestedS3"
}
}
}
}`)
}
type sample struct {
id string `swagger:"required"` // TODO
items []item
rootItem item `json:"root" description:"root desc"`
}
type item struct {
itemName string `json:"name"`
}
// clear && go test -v -test.run TestSampleToModelAsJson ...swagger
func TestSampleToModelAsJson(t *testing.T) {
testJsonFromStruct(t, sample{items: []item{}}, `{
"swagger.item": {
"id": "swagger.item",
"required": [
"name"
],
"properties": {
"name": {
"type": "string"
}
}
},
"swagger.sample": {
"id": "swagger.sample",
"required": [
"id",
"items",
"root"
],
"properties": {
"id": {
"type": "string"
},
"items": {
"type": "array",
"items": {
"$ref": "swagger.item"
}
},
"root": {
"$ref": "swagger.item",
"description": "root desc"
}
}
}
}`)
}
func TestJsonTags(t *testing.T) {
type X struct {
A string
B string `json:"-"`
C int `json:",string"`
D int `json:","`
}
expected := `{
"swagger.X": {
"id": "swagger.X",
"required": [
"A",
"C",
"D"
],
"properties": {
"A": {
"type": "string"
},
"C": {
"type": "string"
},
"D": {
"type": "integer",
"format": "int32"
}
}
}
}`
testJsonFromStruct(t, X{}, expected)
}
func TestJsonTagOmitempty(t *testing.T) {
type X struct {
A int `json:",omitempty"`
B int `json:"C,omitempty"`
}
expected := `{
"swagger.X": {
"id": "swagger.X",
"properties": {
"A": {
"type": "integer",
"format": "int32"
},
"C": {
"type": "integer",
"format": "int32"
}
}
}
}`
testJsonFromStruct(t, X{}, expected)
}
func TestJsonTagName(t *testing.T) {
type X struct {
A string `json:"B"`
}
expected := `{
"swagger.X": {
"id": "swagger.X",
"required": [
"B"
],
"properties": {
"B": {
"type": "string"
}
}
}
}`
testJsonFromStruct(t, X{}, expected)
}
func TestAnonymousStruct(t *testing.T) {
type X struct {
A struct {
B int
}
}
expected := `{
"swagger.X": {
"id": "swagger.X",
"required": [
"A"
],
"properties": {
"A": {
"$ref": "swagger.X.A"
}
}
},
"swagger.X.A": {
"id": "swagger.X.A",
"required": [
"B"
],
"properties": {
"B": {
"type": "integer",
"format": "int32"
}
}
}
}`
testJsonFromStruct(t, X{}, expected)
}
func TestAnonymousPtrStruct(t *testing.T) {
type X struct {
A *struct {
B int
}
}
expected := `{
"swagger.X": {
"id": "swagger.X",
"required": [
"A"
],
"properties": {
"A": {
"$ref": "swagger.X.A"
}
}
},
"swagger.X.A": {
"id": "swagger.X.A",
"required": [
"B"
],
"properties": {
"B": {
"type": "integer",
"format": "int32"
}
}
}
}`
testJsonFromStruct(t, X{}, expected)
}
func TestAnonymousArrayStruct(t *testing.T) {
type X struct {
A []struct {
B int
}
}
expected := `{
"swagger.X": {
"id": "swagger.X",
"required": [
"A"
],
"properties": {
"A": {
"type": "array",
"items": {
"$ref": "swagger.X.A"
}
}
}
},
"swagger.X.A": {
"id": "swagger.X.A",
"required": [
"B"
],
"properties": {
"B": {
"type": "integer",
"format": "int32"
}
}
}
}`
testJsonFromStruct(t, X{}, expected)
}
func TestAnonymousPtrArrayStruct(t *testing.T) {
type X struct {
A *[]struct {
B int
}
}
expected := `{
"swagger.X": {
"id": "swagger.X",
"required": [
"A"
],
"properties": {
"A": {
"type": "array",
"items": {
"$ref": "swagger.X.A"
}
}
}
},
"swagger.X.A": {
"id": "swagger.X.A",
"required": [
"B"
],
"properties": {
"B": {
"type": "integer",
"format": "int32"
}
}
}
}`
testJsonFromStruct(t, X{}, expected)
}
// go test -v -test.run TestEmbeddedStruct_Issue98 ...swagger
func TestEmbeddedStruct_Issue98(t *testing.T) {
type Y struct {
A int
}
type X struct {
Y
}
testJsonFromStruct(t, X{}, `{
"swagger.X": {
"id": "swagger.X",
"required": [
"A"
],
"properties": {
"A": {
"type": "integer",
"format": "int32"
}
}
}
}`)
}
type Dataset struct {
Names []string
}
// clear && go test -v -test.run TestIssue85 ...swagger
func TestIssue85(t *testing.T) {
anon := struct{ Datasets []Dataset }{}
testJsonFromStruct(t, anon, `{
"struct { Datasets ||swagger.Dataset }": {
"id": "struct { Datasets ||swagger.Dataset }",
"required": [
"Datasets"
],
"properties": {
"Datasets": {
"type": "array",
"items": {
"$ref": "swagger.Dataset"
}
}
}
},
"swagger.Dataset": {
"id": "swagger.Dataset",
"required": [
"Names"
],
"properties": {
"Names": {
"type": "array",
"items": {
"type": "string"
}
}
}
}
}`)
}
type File struct {
History []File
HistoryPtrs []*File
}
// go test -v -test.run TestRecursiveStructure ...swagger
func TestRecursiveStructure(t *testing.T) {
testJsonFromStruct(t, File{}, `{
"swagger.File": {
"id": "swagger.File",
"required": [
"History",
"HistoryPtrs"
],
"properties": {
"History": {
"type": "array",
"items": {
"$ref": "swagger.File"
}
},
"HistoryPtrs": {
"type": "array",
"items": {
"$ref": "swagger.File"
}
}
}
}
}`)
}
type A1 struct {
B struct {
Id int
Comment string `json:"comment,omitempty"`
}
}
// go test -v -test.run TestEmbeddedStructA1 ...swagger
func TestEmbeddedStructA1(t *testing.T) {
testJsonFromStruct(t, A1{}, `{
"swagger.A1": {
"id": "swagger.A1",
"required": [
"B"
],
"properties": {
"B": {
"$ref": "swagger.A1.B"
}
}
},
"swagger.A1.B": {
"id": "swagger.A1.B",
"required": [
"Id"
],
"properties": {
"Id": {
"type": "integer",
"format": "int32"
},
"comment": {
"type": "string"
}
}
}
}`)
}
type A2 struct {
C
}
type C struct {
Id int `json:"B"`
Comment string `json:"comment,omitempty"`
Secure bool `json:"secure"`
}
// go test -v -test.run TestEmbeddedStructA2 ...swagger
func TestEmbeddedStructA2(t *testing.T) {
testJsonFromStruct(t, A2{}, `{
"swagger.A2": {
"id": "swagger.A2",
"required": [
"B",
"secure"
],
"properties": {
"B": {
"type": "integer",
"format": "int32"
},
"comment": {
"type": "string"
},
"secure": {
"type": "boolean"
}
}
}
}`)
}
type A3 struct {
B D
}
type D struct {
Id int
}
// clear && go test -v -test.run TestStructA3 ...swagger
func TestStructA3(t *testing.T) {
testJsonFromStruct(t, A3{}, `{
"swagger.A3": {
"id": "swagger.A3",
"required": [
"B"
],
"properties": {
"B": {
"$ref": "swagger.D"
}
}
},
"swagger.D": {
"id": "swagger.D",
"required": [
"Id"
],
"properties": {
"Id": {
"type": "integer",
"format": "int32"
}
}
}
}`)
}
type A4 struct {
D "json:,inline"
}
// clear && go test -v -test.run TestStructA4 ...swagger
func TestEmbeddedStructA4(t *testing.T) {
testJsonFromStruct(t, A4{}, `{
"swagger.A4": {
"id": "swagger.A4",
"required": [
"Id"
],
"properties": {
"Id": {
"type": "integer",
"format": "int32"
}
}
}
}`)
}
type A5 struct {
D `json:"d"`
}
// clear && go test -v -test.run TestStructA5 ...swagger
func TestEmbeddedStructA5(t *testing.T) {
testJsonFromStruct(t, A5{}, `{
"swagger.A5": {
"id": "swagger.A5",
"required": [
"d"
],
"properties": {
"d": {
"$ref": "swagger.D"
}
}
},
"swagger.D": {
"id": "swagger.D",
"required": [
"Id"
],
"properties": {
"Id": {
"type": "integer",
"format": "int32"
}
}
}
}`)
}
type D2 struct {
id int
D []D
}
type A6 struct {
D2 "json:,inline"
}
// clear && go test -v -test.run TestStructA4 ...swagger
func TestEmbeddedStructA6(t *testing.T) {
testJsonFromStruct(t, A6{}, `{
"swagger.A6": {
"id": "swagger.A6",
"required": [
"id",
"D"
],
"properties": {
"D": {
"type": "array",
"items": {
"$ref": "swagger.D"
}
},
"id": {
"type": "integer",
"format": "int32"
}
}
},
"swagger.D": {
"id": "swagger.D",
"required": [
"Id"
],
"properties": {
"Id": {
"type": "integer",
"format": "int32"
}
}
}
}`)
}
type ObjectId []byte
type Region struct {
Id ObjectId `bson:"_id" json:"id"`
Name string `bson:"name" json:"name"`
Type string `bson:"type" json:"type"`
}
// clear && go test -v -test.run TestRegion_Issue113 ...swagger
func TestRegion_Issue113(t *testing.T) {
testJsonFromStruct(t, []Region{}, `{
"||swagger.Region": {
"id": "||swagger.Region",
"properties": {}
},
"swagger.Region": {
"id": "swagger.Region",
"required": [
"id",
"name",
"type"
],
"properties": {
"id": {
"type": "string"
},
"name": {
"type": "string"
},
"type": {
"type": "string"
}
}
}
}`)
}
// clear && go test -v -test.run TestIssue158 ...swagger
func TestIssue158(t *testing.T) {
type Address struct {
Country string `json:"country,omitempty"`
}
type Customer struct {
Name string `json:"name"`
Address Address `json:"address"`
}
expected := `{
"swagger.Address": {
"id": "swagger.Address",
"properties": {
"country": {
"type": "string"
}
}
},
"swagger.Customer": {
"id": "swagger.Customer",
"required": [
"name",
"address"
],
"properties": {
"address": {
"$ref": "swagger.Address"
},
"name": {
"type": "string"
}
}
}
}`
testJsonFromStruct(t, Customer{}, expected)
}
func TestPointers(t *testing.T) {
type Vote struct {
What YesNo
}
testJsonFromStruct(t, &Vote{}, `{
"swagger.Vote": {
"id": "swagger.Vote",
"required": [
"What"
],
"properties": {
"What": {
"type": "string"
}
}
}
}`)
}
func TestSlices(t *testing.T) {
type Address struct {
Country string `json:"country,omitempty"`
}
expected := `{
"swagger.Address": {
"id": "swagger.Address",
"properties": {
"country": {
"type": "string"
}
}
},
"swagger.Customer": {
"id": "swagger.Customer",
"required": [
"name",
"addresses"
],
"properties": {
"addresses": {
"type": "array",
"items": {
"$ref": "swagger.Address"
}
},
"name": {
"type": "string"
}
}
}
}`
// both slices (with pointer value and with type value) should have equal swagger representation
{
type Customer struct {
Name string `json:"name"`
Addresses []Address `json:"addresses"`
}
testJsonFromStruct(t, Customer{}, expected)
}
{
type Customer struct {
Name string `json:"name"`
Addresses []*Address `json:"addresses"`
}
testJsonFromStruct(t, Customer{}, expected)
}
}
type Name struct {
Value string
}
func (n Name) PostBuildModel(m *Model) *Model {
m.Description = "titles must be upcase"
return m
}
type TOC struct {
Titles []Name
}
type Discography struct {
Title Name
TOC
}
// clear && go test -v -test.run TestEmbeddedStructPull204 ...swagger
func TestEmbeddedStructPull204(t *testing.T) {
b := Discography{}
testJsonFromStruct(t, b, `
{
"swagger.Discography": {
"id": "swagger.Discography",
"required": [
"Title",
"Titles"
],
"properties": {
"Title": {
"$ref": "swagger.Name"
},
"Titles": {
"type": "array",
"items": {
"$ref": "swagger.Name"
}
}
}
},
"swagger.Name": {
"id": "swagger.Name",
"required": [
"Value"
],
"properties": {
"Value": {
"type": "string"
}
}
}
}
`)
}
type AddressWithMethod struct {
Country string `json:"country,omitempty"`
PostCode int `json:"postcode,omitempty"`
}
func (AddressWithMethod) SwaggerDoc() map[string]string {
return map[string]string{
"": "Address doc",
"country": "Country doc",
"postcode": "PostCode doc",
}
}
func TestDocInMethodSwaggerDoc(t *testing.T) {
expected := `{
"swagger.AddressWithMethod": {
"id": "swagger.AddressWithMethod",
"description": "Address doc",
"properties": {
"country": {
"type": "string",
"description": "Country doc"
},
"postcode": {
"type": "integer",
"format": "int32",
"description": "PostCode doc"
}
}
}
}`
testJsonFromStruct(t, AddressWithMethod{}, expected)
}
type RefDesc struct {
f1 *int64 `description:"desc"`
}
func TestPtrDescription(t *testing.T) {
b := RefDesc{}
expected := `{
"swagger.RefDesc": {
"id": "swagger.RefDesc",
"required": [
"f1"
],
"properties": {
"f1": {
"type": "integer",
"format": "int64",
"description": "desc"
}
}
}
}`
testJsonFromStruct(t, b, expected)
}
type A struct {
B `json:",inline"`
C1 `json:"metadata,omitempty"`
}
type B struct {
SB string
}
type C1 struct {
SC string
}
func (A) SwaggerDoc() map[string]string {
return map[string]string{
"": "A struct",
"B": "B field", // We should not get anything from this
"metadata": "C1 field",
}
}
func (B) SwaggerDoc() map[string]string {
return map[string]string{
"": "B struct",
"SB": "SB field",
}
}
func (C1) SwaggerDoc() map[string]string {
return map[string]string{
"": "C1 struct",
"SC": "SC field",
}
}
func TestNestedStructDescription(t *testing.T) {
expected := `
{
"swagger.A": {
"id": "swagger.A",
"description": "A struct",
"required": [
"SB"
],
"properties": {
"SB": {
"type": "string",
"description": "SB field"
},
"metadata": {
"$ref": "swagger.C1",
"description": "C1 field"
}
}
},
"swagger.C1": {
"id": "swagger.C1",
"description": "C1 struct",
"required": [
"SC"
],
"properties": {
"SC": {
"type": "string",
"description": "SC field"
}
}
}
}
`
testJsonFromStruct(t, A{}, expected)
}
// This tests a primitive with type overrides in the struct tags
type FakeInt int
type E struct {
Id FakeInt `type:"integer"`
IP net.IP `type:"string"`
}
func TestOverridenTypeTagE1(t *testing.T) {
expected := `
{
"swagger.E": {
"id": "swagger.E",
"required": [
"Id",
"IP"
],
"properties": {
"Id": {
"type": "integer"
},
"IP": {
"type": "string"
}
}
}
}
`
testJsonFromStruct(t, E{}, expected)
}
type XmlNamed struct {
XMLName xml.Name `xml:"user"`
Id string `json:"id" xml:"id"`
Name string `json:"name" xml:"name"`
}
func TestXmlNameStructs(t *testing.T) {
expected := `
{
"swagger.XmlNamed": {
"id": "swagger.XmlNamed",
"required": [
"id",
"name"
],
"properties": {
"id": {
"type": "string"
},
"name": {
"type": "string"
}
}
}
}
`
testJsonFromStruct(t, XmlNamed{}, expected)
}
func TestNameCustomization(t *testing.T) {
expected := `
{
"swagger.A": {
"id": "swagger.A",
"description": "A struct",
"required": [
"SB"
],
"properties": {
"SB": {
"type": "string",
"description": "SB field"
},
"metadata": {
"$ref": "new.swagger.SpecialC1",
"description": "C1 field"
}
}
},
"new.swagger.SpecialC1": {
"id": "new.swagger.SpecialC1",
"description": "C1 struct",
"required": [
"SC"
],
"properties": {
"SC": {
"type": "string",
"description": "SC field"
}
}
}
}`
testJsonFromStructWithConfig(t, A{}, expected, &Config{
ModelTypeNameHandler: func(t reflect.Type) (string, bool) {
if t == reflect.TypeOf(C1{}) {
return "new.swagger.SpecialC1", true
}
return "", false
},
})
}