func TestSetOperationParamsError(t *testing.T) {
	g := gen(t)
	op := &Operation{}
	typ := reflect.TypeOf([]string{})
	err := g.setOperationParams(op, typ, typ, false, "/")
	assert.NotNil(t, err)
	type T struct {
		B string `path:"B"`
	}
	typ = reflect.TypeOf(T{})
	err = g.setOperationParams(op, typ, typ, false, "/{a}/{B}")
	assert.NotNil(t, err)
}
TestSetOperationParamsError tests the various error
cases that can occur while adding parameters to an op.
package openapi
import (
	"encoding/json"
	"io/ioutil"
	"math"
	"reflect"
	"testing"
	"time"
	"github.com/Pallinder/go-randomdata"
	"github.com/loopfz/gadgeto/tonic"
	"github.com/stretchr/testify/assert"
)
var genConfig = &SpecGenConfig{
	ValidatorTag:      tonic.ValidationTag,
	PathLocationTag:   tonic.PathTag,
	QueryLocationTag:  tonic.QueryTag,
	HeaderLocationTag: tonic.HeaderTag,
	EnumTag:           tonic.EnumTag,
	DefaultTag:        tonic.DefaultTag,
}
var rt = reflect.TypeOf
type (
	W struct {
		A, B string
	}
	u struct {
		S int
	}
	q int
	X struct {
		*X  
		*Y
		A string `validate:"required"`
		B *int
		C bool `deprecated:"true"`
		D []*Y
		E [3]*X
		F *X
		G *Y
		H map[int]*Y  
		*u
		uu *u  
		q      
	}
	Y struct {
		H float32   `validate:"required"`
		I time.Time `format:"date"`
		J *uint8    `deprecated:"oui"`  
		K *Z        `validate:"required"`
		N struct {
			Na, Nb string
			Nc     time.Duration
		}
		l int  
		M int `json:"-"`
	}
	Z map[string]*Y
)
func (*X) TypeName() string { return "XXX" }
func (*W) Format() string   { return "wallet" }
func (*W) Type() string     { return "string" }
func TestStructFieldName(t *testing.T) {
	type T struct {
		A  string `name:"A"`
		Ba string `name:""`
		AB string `name:"-"`
		B  struct{}
	}
	to := reflect.TypeOf(T{})
	assert.Equal(t, "A", fieldNameFromTag(to.Field(0), "name"))
	assert.Equal(t, "Ba", fieldNameFromTag(to.Field(1), "name"))
	assert.Equal(t, "", fieldNameFromTag(to.Field(2), "name"))
}
func TestAddTag(t *testing.T) {
	g := gen(t)
	g.api.Tags = append(g.api.Tags, nil)
	g.AddTag("", "Test routes")
	assert.Len(t, g.API().Tags, 1)
	g.AddTag("Test", "Test routes")
	assert.Len(t, g.API().Tags, 2)
	tag := g.API().Tags[1]
	assert.NotNil(t, tag)
	assert.Equal(t, tag.Name, "Test")
	assert.Equal(t, tag.Description, "Test routes")
	g.AddTag("Test", "Routes test")
	assert.Equal(t, tag.Description, "Routes test")
	g.AddTag("A", "")
	assert.Len(t, g.API().Tags, 3)
	tag = g.API().Tags[1]
	assert.Equal(t, "A", tag.Name)
}
func TestSchemaFromPrimitiveType(t *testing.T) {
	g := gen(t)
	schema := g.newSchemaFromType(rt(new(int64)))
	if schema.Schema == nil {
		t.Error("expected an inlined schema, got a schema reference")
	}
	assert.Equal(t, "integer", schema.Type)
	assert.Equal(t, "int64", schema.Format)
	assert.True(t, schema.Nullable)
}
func TestSchemaFromInterface(t *testing.T) {
	g := gen(t)
	schema := g.newSchemaFromType(tofEmptyInterface)
	assert.NotNil(t, schema)
	assert.Empty(t, schema.Type)
	assert.Empty(t, schema.Format)
	assert.True(t, schema.Nullable)
	assert.NotEmpty(t, schema.Description)
}
func TestSchemaFromUnsupportedType(t *testing.T) {
	g := gen(t)
	schema := g.newSchemaFromType(nil)
	assert.Nil(t, schema)
	schema = g.newSchemaFromType(rt(func() {}))
	assert.Nil(t, schema)
	assert.Len(t, g.Errors(), 1)
	assert.Implements(t, (*error)(nil), g.Errors()[0])
	assert.NotEmpty(t, g.Errors()[0])
}
func TestSchemaFromMapWithUnsupportedKeys(t *testing.T) {
	g := gen(t)
	schema := g.newSchemaFromType(rt(map[int]string{}))
	assert.Nil(t, schema)
	assert.Len(t, g.Errors(), 1)
	assert.Implements(t, (*error)(nil), g.Errors()[0])
	assert.NotEmpty(t, g.Errors()[0].Error())
}
func TestSchemaFromComplex(t *testing.T) {
	g := gen(t)
	g.UseFullSchemaNames(false)
	sor := g.newSchemaFromType(rt(new(X)))
	assert.NotNil(t, sor)
	b, err := json.Marshal(sor)
	if err != nil {
		t.Error(err)
	}
	assert.Equal(t, `{"$ref":"#/components/schemas/XXX"}`, string(b))
	schema := g.resolveSchema(sor)
	assert.NotNil(t, schema)
	actual, err := json.Marshal(schema)
	if err != nil {
		t.Error(err)
	}
	expected, err := ioutil.ReadFile("../testdata/schemas/X.json")
	if err != nil {
		t.Error(err)
	}
	m, err := diffJSON(actual, expected)
	if err != nil {
		t.Error(err)
	}
	if !m {
		t.Error("expected json outputs to be equal")
	}
	sor = g.API().Components.Schemas["Y"]
	schema = g.resolveSchema(sor)
	assert.NotNil(t, schema)
	actual, err = json.Marshal(schema)
	if err != nil {
		t.Error(err)
	}
	expected, err = ioutil.ReadFile("../testdata/schemas/Y.json")
	if err != nil {
		t.Error(err)
	}
	m, err = diffJSON(actual, expected)
	if err != nil {
		t.Error(err)
	}
	if !m {
		t.Error("expected json outputs to be equal")
	}
}
func TestNewSchemaFromStructErrors(t *testing.T) {
	g := gen(t)
	sor := g.newSchemaFromStruct(reflect.TypeOf(new(string)))
	assert.Nil(t, sor)
}
func TestNewSchemaFromStructFieldExampleValues(t *testing.T) {
	g := gen(t)
	type T struct {
		A    string    `example:"value"`
		APtr *string   `example:"value"`
		B    int       `example:"1"`
		BPtr *int      `example:"1"`
		C    float64   `example:"0.1"`
		CPtr *float64  `example:"0.1"`
		D    bool      `example:"true"`
		DPtr *bool     `example:"true"`
		EPtr **bool    `example:"false"`
		FPtr ***uint16 `example:"128"`
	}
	typ := reflect.TypeOf(T{})
	sor := g.newSchemaFromStructField(typ.Field(0), false, "A", typ)
	assert.NotNil(t, sor)
	assert.Equal(t, "value", sor.Example)
	sor = g.newSchemaFromStructField(typ.Field(1), false, "APtr", typ)
	assert.NotNil(t, sor)
	assert.Equal(t, "value", sor.Example)
	sor = g.newSchemaFromStructField(typ.Field(2), false, "B", typ)
	assert.NotNil(t, sor)
	assert.Equal(t, int64(1), sor.Example)
	sor = g.newSchemaFromStructField(typ.Field(3), false, "BPtr", typ)
	assert.NotNil(t, sor)
	assert.Equal(t, int64(1), sor.Example)
	sor = g.newSchemaFromStructField(typ.Field(4), false, "C", typ)
	assert.NotNil(t, sor)
	assert.Equal(t, 0.1, sor.Example)
	sor = g.newSchemaFromStructField(typ.Field(5), false, "CPtr", typ)
	assert.NotNil(t, sor)
	assert.Equal(t, 0.1, sor.Example)
	sor = g.newSchemaFromStructField(typ.Field(6), false, "D", typ)
	assert.NotNil(t, sor)
	assert.Equal(t, true, sor.Example)
	sor = g.newSchemaFromStructField(typ.Field(7), false, "DPtr", typ)
	assert.NotNil(t, sor)
	assert.Equal(t, true, sor.Example)
	sor = g.newSchemaFromStructField(typ.Field(8), false, "EPtr", typ)
	assert.NotNil(t, sor)
	assert.Equal(t, false, sor.Example)
	sor = g.newSchemaFromStructField(typ.Field(9), false, "FPtr", typ)
	assert.NotNil(t, sor)
	assert.Equal(t, uint16(128), sor.Example)
}
func TestNewSchemaFromStructFieldErrors(t *testing.T) {
	g := gen(t)
	type T struct {
		A string `validate:"required" default:"foobar"`
		B int    `default:"foobaz"`
		C int    `enum:"a,1,c"`
		D bool   `example:"not-a-bool-value"`
	}
	typ := reflect.TypeOf(T{})
	sor := g.newSchemaFromStructField(typ.Field(0), true, "A", typ)
	assert.NotNil(t, sor)
	assert.Len(t, g.Errors(), 1)
	assert.Implements(t, (*error)(nil), g.Errors()[0])
	assert.NotEmpty(t, g.Errors()[0].Error())
	sor = g.newSchemaFromStructField(typ.Field(1), false, "B", typ)
	assert.NotNil(t, sor)
	assert.Len(t, g.Errors(), 2)
	assert.Implements(t, (*error)(nil), g.Errors()[1])
	assert.NotEmpty(t, g.Errors()[1].Error())
	sor = g.newSchemaFromStructField(typ.Field(2), true, "C", typ)
	assert.NotNil(t, sor)
	assert.Len(t, g.Errors(), 4)
	assert.NotEmpty(t, g.Errors()[2].Error())
	assert.NotEmpty(t, g.Errors()[3].Error())
	sor = g.newSchemaFromStructField(typ.Field(3), false, "D", typ)
	assert.NotNil(t, sor)
	assert.Len(t, g.Errors(), 5)
	assert.NotEmpty(t, g.Errors()[4].Error())
	fe, ok := g.Errors()[4].(*FieldError)
	assert.True(t, ok)
	assert.Equal(t, "D", fe.Name)
	assert.Equal(t, reflect.Bool, fe.Type.Kind())
}
func diffJSON(a, b []byte) (bool, error) {
	var j, j2 interface{}
	if err := json.Unmarshal(a, &j); err != nil {
		return false, err
	}
	if err := json.Unmarshal(b, &j2); err != nil {
		return false, err
	}
	return reflect.DeepEqual(j2, j), nil
}
func TestAddOperation(t *testing.T) {
	type InEmbed struct {
		D int      `query:"xd" enum:"1,2,3" default:"1"`
		E bool     `query:"e"`
		F *string  `json:"f" description:"This is F"`
		G []byte   `validate:"required"`
		H uint16   `binding:"-"`
		K []string `query:"k" enum:"aaa,bbb,ccc"`
	}
	type inEmbedPrivate struct {
		I string `query:"i"`
	}
	type h string
	type In struct {
		*In  
		*InEmbed
		*inEmbedPrivate
		A int       `path:"a" description:"This is A" deprecated:"oui"`
		B time.Time `query:"b" validate:"required" description:"This is B"`
		C string    `header:"X-Test-C" description:"This is C" default:"test"`
		d int        
		E int       `path:"a"`  
		F *string   `json:"f"`  
		G *inEmbedPrivate
		h  
	}
	type CustomError struct{}
	var Header string
	g := gen(t)
	g.UseFullSchemaNames(false)
	g.SetSortParams(true)
	path := "/test/:a"
	infos := &OperationInfo{
		ID:          "CreateTest",
		StatusCode:  201,
		Summary:     "ABC",
		Description: "XYZ",
		Deprecated:  true,
		Responses: []*OperationResponse{
			{
				Code:        "400",
				Description: "Bad Request",
				Model:       CustomError{},
			},
			{
				Code:        "5XX",
				Description: "Server Errors",
			},
		},
		Headers: []*ResponseHeader{
			{
				Name:        "X-Test-Header",
				Description: "Test header",
				Model:       Header,
			},
			{
				Name:        "X-Test-Header-Alt",
				Description: "Test header alt",
			},
		},
	}
	_, err := g.AddOperation(path, "POST", "Test", reflect.TypeOf(&In{}), reflect.TypeOf(Z{}), infos)
	if err != nil {
		t.Error(err)
	}
	_, err = g.AddOperation(path, "PUT", "Test", nil, nil, &OperationInfo{
		ID:          "UpdateTest",
		StatusCode:  204,
		Description: "Update a test.",
	})
	if err != nil {
		t.Error(err)
	}
	assert.Len(t, g.API().Paths, 1)
	item, ok := g.API().Paths[rewritePath(path)]
	if !ok {
		t.Errorf("expected to found item for path %s", path)
	}
	assert.NotNil(t, item.POST)
	assert.NotNil(t, item.PUT)
	actual, err := json.Marshal(item)
	if err != nil {
		t.Error(err)
	}
	expected, err := ioutil.ReadFile("../testdata/schemas/path-item.json")
	if err != nil {
		t.Error(err)
	}
	m, err := diffJSON(actual, expected)
	if err != nil {
		t.Error(err)
	}
	if !m {
		t.Error("expected json outputs to be equal")
	}
	_, err = g.AddOperation(path, "POST", "Test", reflect.TypeOf(&In{}), reflect.TypeOf(Z{}), infos)
	assert.NotNil(t, err)
	_, err = g.AddOperation("/", "GET", "", reflect.TypeOf(new(string)), nil, nil)
	assert.NotNil(t, err)
}
func TestTypeName(t *testing.T) {
	g, err := NewGenerator(genConfig)
	if err != nil {
		t.Error(err)
	}
	name := g.typeName(rt(new(X)))
	assert.Equal(t, "XXX", name)
	err = g.OverrideTypeName(rt(new(X)), "")
	assert.NotNil(t, err)
	assert.Equal(t, "XXX", g.typeName(rt(new(X))))
	g.OverrideTypeName(rt(new(X)), "xXx")
	assert.Equal(t, "xXx", g.typeName(rt(X{})))
	err = g.OverrideTypeName(rt(new(X)), "YYY")
	assert.NotNil(t, err)
	assert.Equal(t, "OpenapiY", g.typeName(rt(new(Y))))
	g.UseFullSchemaNames(false)
	assert.Equal(t, "Y", g.typeName(rt(Y{})))
	assert.Equal(t, "", g.typeName(rt(struct{}{})))
}
func TestSetInfo(t *testing.T) {
	g := gen(t)
	infos := &Info{
		Description: "Test",
	}
	g.SetInfo(infos)
	assert.NotNil(t, g.API().Info)
	assert.Equal(t, infos, g.API().Info)
}
func TestSetOperationByMethod(t *testing.T) {
	pi := &PathItem{}
	for method, ptr := range map[string]**Operation{
		"GET":     &pi.GET,
		"POST":    &pi.POST,
		"PUT":     &pi.PUT,
		"PATCH":   &pi.PATCH,
		"DELETE":  &pi.DELETE,
		"HEAD":    &pi.HEAD,
		"OPTIONS": &pi.OPTIONS,
		"TRACE":   &pi.TRACE,
	} {
		desc := randomdata.SillyName()
		op := &Operation{
			Description: desc,
		}
		setOperationBymethod(pi, op, method)
		assert.Equal(t, op, *ptr)
		assert.Equal(t, desc, (*ptr).Description)
	}
}
func TestSetOperationResponseError(t *testing.T) {
	g := gen(t)
	op := &Operation{
		Responses: make(Responses),
	}
	err := g.setOperationResponse(op, reflect.TypeOf(new(string)), "200", "application/json", "", nil, nil, nil)
	assert.Nil(t, err)
	err = g.setOperationResponse(op, reflect.TypeOf(new(int)), "200", "application/xml", "", nil, nil, nil)
	assert.NotNil(t, err)
	err = g.setOperationResponse(op, reflect.TypeOf(new(bool)), "two-hundred", "", "", nil, nil, nil)
	assert.NotNil(t, err)
	err = g.setOperationResponse(op, reflect.TypeOf(new(bool)), "777", "", "", nil, nil, nil)
	assert.NotNil(t, err)
	err = g.setOperationResponse(op, reflect.TypeOf(new(bool)), "404", "", "", nil, "notFoundExample", map[string]interface{}{"badRequest": "message"})
	assert.NotNil(t, err)
}
func TestSetOperationResponseExample(t *testing.T) {
	g := gen(t)
	op := &Operation{
		Responses: make(Responses),
	}
	error1 := map[string]interface{}{"error": "message1"}
	err := g.setOperationResponse(op, reflect.TypeOf(new(string)), "400", "application/json", "", nil, error1, nil)
	assert.Nil(t, err)
	mt := op.Responses["400"].Response.Content["application/json"].MediaType
	assert.Equal(t, error1, mt.Example)
	assert.Nil(t, mt.Examples)
}
func TestSetOperationResponseExamples(t *testing.T) {
	g := gen(t)
	op := &Operation{
		Responses: make(Responses),
	}
	error1 := map[string]interface{}{"error": "message1"}
	error2 := map[string]interface{}{"error": "message2"}
	err := g.setOperationResponse(op, reflect.TypeOf(new(string)), "400", "application/json", "", nil, nil,
		map[string]interface{}{
			"one": error1,
			"two": error2,
		},
	)
	assert.Nil(t, err)
	mt := op.Responses["400"].Response.Content["application/json"].MediaType
	assert.Equal(t, 2, len(mt.Examples))
	assert.Equal(t, error1, mt.Examples["one"].Example.Value)
	assert.Equal(t, error2, mt.Examples["two"].Example.Value)
	assert.Nil(t, mt.Example)
}