github.com/go-swagger/go-swagger@v0.31.0/generator/model_test.go (about)

     1  // Copyright 2015 go-swagger maintainers
     2  //
     3  // Licensed under the Apache License, Version 2.0 (the "License");
     4  // you may not use this file except in compliance with the License.
     5  // You may obtain a copy of the License at
     6  //
     7  //    http://www.apache.org/licenses/LICENSE-2.0
     8  //
     9  // Unless required by applicable law or agreed to in writing, software
    10  // distributed under the License is distributed on an "AS IS" BASIS,
    11  // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    12  // See the License for the specific language governing permissions and
    13  // limitations under the License.
    14  
    15  package generator
    16  
    17  import (
    18  	"bytes"
    19  	"fmt"
    20  	"os"
    21  	"path/filepath"
    22  	"regexp"
    23  	"strconv"
    24  	"strings"
    25  	"testing"
    26  	"text/template"
    27  
    28  	"github.com/go-openapi/loads"
    29  	"github.com/go-openapi/swag"
    30  	"github.com/stretchr/testify/assert"
    31  	"github.com/stretchr/testify/require"
    32  )
    33  
    34  type templateTest struct {
    35  	t        testing.TB
    36  	template *template.Template
    37  }
    38  
    39  func (tt *templateTest) assertRender(data interface{}, expected string) (success bool) {
    40  	buf := bytes.NewBuffer(nil)
    41  	defer func() {
    42  		success = !tt.t.Failed()
    43  	}()
    44  
    45  	require.NoError(tt.t, tt.template.Execute(buf, data))
    46  
    47  	trimmed := strings.TrimLeft(buf.String(), "\n\t ")
    48  	exp := strings.TrimLeft(expected, "\n\t ")
    49  	assert.Equal(tt.t, exp, trimmed)
    50  
    51  	return
    52  }
    53  
    54  func TestGenerateModel_Sanity(t *testing.T) {
    55  	t.Parallel()
    56  
    57  	// just checks if it can render and format these things
    58  	specDoc, err := loads.Spec("../fixtures/codegen/todolist.models.yml")
    59  	require.NoError(t, err)
    60  
    61  	definitions := specDoc.Spec().Definitions
    62  
    63  	t.Run("mode sanity check", func(t *testing.T) {
    64  		for k, schema := range definitions {
    65  			opts := opts()
    66  			genModel, err := makeGenDefinition(k, "models", schema, specDoc, opts)
    67  			require.NoError(t, err)
    68  
    69  			rendered := bytes.NewBuffer(nil)
    70  
    71  			require.NoErrorf(t, opts.templates.MustGet("model").Execute(rendered, genModel),
    72  				"Unexpected error while rendering models for fixtures/codegen/todolist.models.yml: %v", err)
    73  
    74  			_, err = opts.LanguageOpts.FormatContent(strings.ToLower(k)+".go", rendered.Bytes())
    75  			require.NoError(t, err)
    76  		}
    77  	})
    78  }
    79  
    80  func TestGenerateModel_DocString(t *testing.T) {
    81  	funcMap := FuncMapFunc(DefaultLanguageFunc())
    82  	templ := template.Must(template.New("docstring").Funcs(funcMap).Parse(string(assets["docstring.gotmpl"])))
    83  	tt := templateTest{t, templ}
    84  
    85  	var gmp GenSchema
    86  	gmp.Title = "The title of the property"
    87  	gmp.Description = "The description of the property"
    88  	expected := `The title of the property
    89  //
    90  // The description of the property`
    91  	tt.assertRender(gmp, expected)
    92  
    93  	gmp.Title = ""
    94  	expected = `The description of the property`
    95  	tt.assertRender(gmp, expected)
    96  
    97  	gmp.Description = ""
    98  	gmp.Name = "theModel"
    99  	expected = `the model`
   100  	tt.assertRender(gmp, expected)
   101  }
   102  
   103  func TestGenerateModel_PropertyValidation(t *testing.T) {
   104  	funcMap := FuncMapFunc(DefaultLanguageFunc())
   105  	templ := template.Must(template.New("propertyValidationDocString").Funcs(funcMap).Parse(string(assets["validation/structfield.gotmpl"])))
   106  	tt := templateTest{t, templ}
   107  
   108  	var gmp GenSchema
   109  	gmp.Required = true
   110  	tt.assertRender(gmp, `
   111  // Required: true`)
   112  	var fl float64 = 10
   113  	var in1 int64 = 20
   114  	var in2 int64 = 30
   115  	gmp.Maximum = &fl
   116  	gmp.ExclusiveMaximum = true
   117  	gmp.Minimum = &fl
   118  	gmp.ExclusiveMinimum = true
   119  	gmp.MaxLength = &in1
   120  	gmp.MinLength = &in1
   121  	gmp.Pattern = "\\w[\\w- ]+"
   122  	gmp.MaxItems = &in2
   123  	gmp.MinItems = &in2
   124  	gmp.UniqueItems = true
   125  
   126  	tt.assertRender(gmp, `
   127  // Required: true
   128  // Maximum: < 10
   129  // Minimum: > 10
   130  // Max Length: 20
   131  // Min Length: 20
   132  // Pattern: \w[\w- ]+
   133  // Max Items: 30
   134  // Min Items: 30
   135  // Unique: true`)
   136  
   137  	gmp.Required = false
   138  	gmp.ExclusiveMaximum = false
   139  	gmp.ExclusiveMinimum = false
   140  	tt.assertRender(gmp, `
   141  // Maximum: 10
   142  // Minimum: 10
   143  // Max Length: 20
   144  // Min Length: 20
   145  // Pattern: \w[\w- ]+
   146  // Max Items: 30
   147  // Min Items: 30
   148  // Unique: true`)
   149  }
   150  
   151  func TestGenerateModel_SchemaField(t *testing.T) {
   152  	tt := templateTest{t, templates.MustGet("model").Lookup("structfield")}
   153  
   154  	var gmp GenSchema
   155  	gmp.Name = "some name"
   156  	gmp.OriginalName = "some name"
   157  	gmp.resolvedType = resolvedType{GoType: "string", IsPrimitive: true, IsEmptyOmitted: true}
   158  	gmp.Title = "The title of the property"
   159  	gmp.CustomTag = "mytag:\"foobar,foobaz\""
   160  
   161  	tt.assertRender(&gmp, `// The title of the property
   162  `+"SomeName string `json:\"some name,omitempty\" mytag:\"foobar,foobaz\"`\n")
   163  
   164  	var fl float64 = 10
   165  	var in1 int64 = 20
   166  	var in2 int64 = 30
   167  
   168  	gmp.Description = "The description of the property"
   169  	gmp.Required = true
   170  	gmp.Maximum = &fl
   171  	gmp.ExclusiveMaximum = true
   172  	gmp.Minimum = &fl
   173  	gmp.ExclusiveMinimum = true
   174  	gmp.MaxLength = &in1
   175  	gmp.MinLength = &in1
   176  	gmp.Pattern = "\\w[\\w- ]+"
   177  	gmp.MaxItems = &in2
   178  	gmp.MinItems = &in2
   179  	gmp.UniqueItems = true
   180  	gmp.ReadOnly = true
   181  	gmp.StructTags = []string{"json", "db", "example"}
   182  	gmp.Example = "some example\""
   183  	tt.assertRender(&gmp, `// The title of the property
   184  //
   185  // The description of the property
   186  // Example: some example"
   187  // Required: true
   188  // Read Only: true
   189  // Maximum: < 10
   190  // Minimum: > 10
   191  // Max Length: 20
   192  // Min Length: 20
   193  // Pattern: \w[\w- ]+
   194  // Max Items: 30
   195  // Min Items: 30
   196  // Unique: true
   197  `+"SomeName string `json:\"some name\" db:\"some name\" example:\"some example\\\"\" mytag:\"foobar,foobaz\"`\n")
   198  
   199  	gmp.Example = "some example``"
   200  	tt.assertRender(&gmp, `// The title of the property
   201  //
   202  // The description of the property
   203  // Example: some example`+"``"+`
   204  // Required: true
   205  // Read Only: true
   206  // Maximum: < 10
   207  // Minimum: > 10
   208  // Max Length: 20
   209  // Min Length: 20
   210  // Pattern: \w[\w- ]+
   211  // Max Items: 30
   212  // Min Items: 30
   213  // Unique: true
   214  `+"SomeName string \"json:\\\"some name\\\" db:\\\"some name\\\" example:\\\"some example``\\\" mytag:\\\"foobar,foobaz\\\"\"\n")
   215  }
   216  
   217  var schTypeGenDataSimple = []struct {
   218  	Value    GenSchema
   219  	Expected string
   220  }{
   221  	{GenSchema{resolvedType: resolvedType{GoType: "string", IsPrimitive: true}}, "string"},
   222  	{GenSchema{resolvedType: resolvedType{GoType: "string", IsPrimitive: true, IsNullable: true}}, "*string"},
   223  	{GenSchema{resolvedType: resolvedType{GoType: "bool", IsPrimitive: true}}, "bool"},
   224  	{GenSchema{resolvedType: resolvedType{GoType: "int32", IsPrimitive: true}}, "int32"},
   225  	{GenSchema{resolvedType: resolvedType{GoType: "int64", IsPrimitive: true}}, "int64"},
   226  	{GenSchema{resolvedType: resolvedType{GoType: "float32", IsPrimitive: true}}, "float32"},
   227  	{GenSchema{resolvedType: resolvedType{GoType: "float64", IsPrimitive: true}}, "float64"},
   228  	{GenSchema{resolvedType: resolvedType{GoType: "strfmt.Base64", IsPrimitive: true}}, "strfmt.Base64"},
   229  	{GenSchema{resolvedType: resolvedType{GoType: "strfmt.Date", IsPrimitive: true}}, "strfmt.Date"},
   230  	{GenSchema{resolvedType: resolvedType{GoType: "strfmt.DateTime", IsPrimitive: true}}, "strfmt.DateTime"},
   231  	{GenSchema{resolvedType: resolvedType{GoType: "strfmt.URI", IsPrimitive: true}}, "strfmt.URI"},
   232  	{GenSchema{resolvedType: resolvedType{GoType: "strfmt.Email", IsPrimitive: true}}, "strfmt.Email"},
   233  	{GenSchema{resolvedType: resolvedType{GoType: "strfmt.Hostname", IsPrimitive: true}}, "strfmt.Hostname"},
   234  	{GenSchema{resolvedType: resolvedType{GoType: "strfmt.IPv4", IsPrimitive: true}}, "strfmt.IPv4"},
   235  	{GenSchema{resolvedType: resolvedType{GoType: "strfmt.IPv6", IsPrimitive: true}}, "strfmt.IPv6"},
   236  	{GenSchema{resolvedType: resolvedType{GoType: "strfmt.UUID", IsPrimitive: true}}, "strfmt.UUID"},
   237  	{GenSchema{resolvedType: resolvedType{GoType: "strfmt.UUID3", IsPrimitive: true}}, "strfmt.UUID3"},
   238  	{GenSchema{resolvedType: resolvedType{GoType: "strfmt.UUID4", IsPrimitive: true}}, "strfmt.UUID4"},
   239  	{GenSchema{resolvedType: resolvedType{GoType: "strfmt.UUID5", IsPrimitive: true}}, "strfmt.UUID5"},
   240  	{GenSchema{resolvedType: resolvedType{GoType: "strfmt.ISBN", IsPrimitive: true}}, "strfmt.ISBN"},
   241  	{GenSchema{resolvedType: resolvedType{GoType: "strfmt.ISBN10", IsPrimitive: true}}, "strfmt.ISBN10"},
   242  	{GenSchema{resolvedType: resolvedType{GoType: "strfmt.ISBN13", IsPrimitive: true}}, "strfmt.ISBN13"},
   243  	{GenSchema{resolvedType: resolvedType{GoType: "strfmt.CreditCard", IsPrimitive: true}}, "strfmt.CreditCard"},
   244  	{GenSchema{resolvedType: resolvedType{GoType: "strfmt.SSN", IsPrimitive: true}}, "strfmt.SSN"},
   245  	{GenSchema{resolvedType: resolvedType{GoType: "strfmt.HexColor", IsPrimitive: true}}, "strfmt.HexColor"},
   246  	{GenSchema{resolvedType: resolvedType{GoType: "strfmt.RGBColor", IsPrimitive: true}}, "strfmt.RGBColor"},
   247  	{GenSchema{resolvedType: resolvedType{GoType: "strfmt.Duration", IsPrimitive: true}}, "strfmt.Duration"},
   248  	{GenSchema{resolvedType: resolvedType{GoType: "strfmt.Password", IsPrimitive: true}}, "strfmt.Password"},
   249  	{GenSchema{resolvedType: resolvedType{GoType: "io.ReadCloser", IsStream: true}}, "io.ReadCloser"},
   250  	{GenSchema{resolvedType: resolvedType{GoType: "interface{}", IsInterface: true}}, "interface{}"},
   251  	{GenSchema{resolvedType: resolvedType{GoType: "[]int32", IsArray: true}}, "[]int32"},
   252  	{GenSchema{resolvedType: resolvedType{GoType: "[]string", IsArray: true}}, "[]string"},
   253  	{GenSchema{resolvedType: resolvedType{GoType: "map[string]int32", IsMap: true}}, "map[string]int32"},
   254  	{GenSchema{resolvedType: resolvedType{GoType: "models.Task", IsComplexObject: true, IsNullable: true, IsAnonymous: false}}, "*models.Task"},
   255  }
   256  
   257  func TestGenSchemaType(t *testing.T) {
   258  	tt := templateTest{t, templates.MustGet("model").Lookup("schemaType")}
   259  	for _, v := range schTypeGenDataSimple {
   260  		tt.assertRender(v.Value, v.Expected)
   261  	}
   262  }
   263  
   264  func TestGenerateModel_Primitives(t *testing.T) {
   265  	tt := templateTest{t, templates.MustGet("model").Lookup("schema")}
   266  	for _, v := range schTypeGenDataSimple {
   267  		v.Value.IncludeValidator = true
   268  		v.Value.IncludeModel = true
   269  		val := v.Value
   270  		val.ReceiverName = "o"
   271  		if val.IsComplexObject {
   272  			continue
   273  		}
   274  		val.Name = "theType"
   275  		exp := v.Expected
   276  		if val.IsInterface || val.IsStream {
   277  			tt.assertRender(&val, "type TheType "+exp+"\n  \n")
   278  			continue
   279  		}
   280  		tt.assertRender(&val, "type TheType "+exp+"\n  \n// Validate validates this the type\nfunc (o theType) Validate(formats strfmt.Registry) error {\n  return nil\n}\n// ContextValidate validates this the type based on context it is used \nfunc (o theType) ContextValidate(ctx context.Context, formats strfmt.Registry) error {\n  return nil\n}\n")
   281  	}
   282  }
   283  
   284  func TestGenerateModel_Zeroes(t *testing.T) {
   285  	for _, v := range schTypeGenDataSimple {
   286  		switch v.Value.GoType {
   287  		// verifying Zero for primitive
   288  		case "string":
   289  			assert.Equal(t, `""`, v.Value.Zero())
   290  		case "bool":
   291  			assert.Equal(t, `false`, v.Value.Zero())
   292  		case "int32", "int64", "float32", "float64":
   293  			assert.Equal(t, `0`, v.Value.Zero())
   294  		// verifying Zero for primitive formatters
   295  		case "strfmt.Date", "strfmt.DateTime", "strfmt.OjbectId": // akin to structs
   296  			rex := regexp.MustCompile(regexp.QuoteMeta(v.Value.GoType) + `{}`)
   297  			assert.True(t, rex.MatchString(v.Value.Zero()))
   298  			k := v.Value
   299  			k.IsAliased = true
   300  			k.AliasedType = k.GoType
   301  			k.GoType = "myAliasedType"
   302  			rex = regexp.MustCompile(regexp.QuoteMeta(k.GoType+"("+k.AliasedType) + `{}` + `\)`)
   303  			assert.True(t, rex.MatchString(k.Zero()))
   304  		case "strfmt.Duration": // akin to integer
   305  			rex := regexp.MustCompile(regexp.QuoteMeta(v.Value.GoType) + `\(\d*\)`)
   306  			assert.True(t, rex.MatchString(v.Value.Zero()))
   307  			k := v.Value
   308  			k.IsAliased = true
   309  			k.AliasedType = k.GoType
   310  			k.GoType = "myAliasedType"
   311  			rex = regexp.MustCompile(regexp.QuoteMeta(k.GoType+"("+k.AliasedType) + `\(\d*\)` + `\)`)
   312  			assert.True(t, rex.MatchString(k.Zero()))
   313  		case "strfmt.Base64": // akin to []byte
   314  			rex := regexp.MustCompile(regexp.QuoteMeta(v.Value.GoType) + `\(\[\]byte.*\)`)
   315  			assert.True(t, rex.MatchString(v.Value.Zero()))
   316  			k := v.Value
   317  			k.IsAliased = true
   318  			k.AliasedType = k.GoType
   319  			k.GoType = "myAliasedType"
   320  			rex = regexp.MustCompile(regexp.QuoteMeta(k.GoType+"("+k.AliasedType) + `\(\[\]byte.*\)` + `\)`)
   321  			assert.True(t, rex.MatchString(k.Zero()))
   322  		case "interface{}":
   323  			assert.Equal(t, `nil`, v.Value.Zero())
   324  		case "io.ReadCloser":
   325  			continue
   326  		default:
   327  			switch {
   328  			case strings.HasPrefix(v.Value.GoType, "[]") || strings.HasPrefix(v.Value.GoType, "map["): // akin to slice or map
   329  				assert.True(t, strings.HasPrefix(v.Value.Zero(), "make("))
   330  
   331  			case strings.HasPrefix(v.Value.GoType, "models."):
   332  				assert.True(t, strings.HasPrefix(v.Value.Zero(), "new("))
   333  
   334  			default: // akin to string
   335  				rex := regexp.MustCompile(regexp.QuoteMeta(v.Value.GoType) + `\(".*"\)`)
   336  				assert.True(t, rex.MatchString(v.Value.Zero()))
   337  				k := v.Value
   338  				k.IsAliased = true
   339  				k.AliasedType = k.GoType
   340  				k.GoType = "myAliasedType"
   341  				rex = regexp.MustCompile(regexp.QuoteMeta(k.GoType+"("+k.AliasedType) + `\(".*"\)` + `\)`)
   342  				assert.True(t, rex.MatchString(k.Zero()))
   343  			}
   344  		}
   345  	}
   346  }
   347  
   348  func TestGenerateModel_Nota(t *testing.T) {
   349  	specDoc, err := loads.Spec("../fixtures/codegen/todolist.models.yml")
   350  	require.NoError(t, err)
   351  
   352  	definitions := specDoc.Spec().Definitions
   353  	k := "Nota"
   354  	schema := definitions[k]
   355  	opts := opts()
   356  	genModel, err := makeGenDefinition(k, "models", schema, specDoc, opts)
   357  	require.NoError(t, err)
   358  
   359  	buf := bytes.NewBuffer(nil)
   360  	require.NoError(t, opts.templates.MustGet("model").Execute(buf, genModel))
   361  
   362  	res := buf.String()
   363  	assertInCode(t, "type Nota map[string]int32", res)
   364  }
   365  
   366  func TestGenerateModel_NotaWithRef(t *testing.T) {
   367  	specDoc, err := loads.Spec("../fixtures/codegen/todolist.models.yml")
   368  	require.NoError(t, err)
   369  
   370  	definitions := specDoc.Spec().Definitions
   371  	k := "NotaWithRef"
   372  	schema := definitions[k]
   373  	opts := opts()
   374  	genModel, err := makeGenDefinition(k, "models", schema, specDoc, opts)
   375  	require.NoError(t, err)
   376  
   377  	buf := bytes.NewBuffer(nil)
   378  	require.NoError(t, opts.templates.MustGet("model").Execute(buf, genModel))
   379  
   380  	ff, err := opts.LanguageOpts.FormatContent("nota_with_ref.go", buf.Bytes())
   381  	require.NoError(t, err)
   382  
   383  	res := string(ff)
   384  	assertInCode(t, "type NotaWithRef map[string]Notable", res)
   385  }
   386  
   387  func TestGenerateModel_NotaWithMeta(t *testing.T) {
   388  	specDoc, err := loads.Spec("../fixtures/codegen/todolist.models.yml")
   389  	require.NoError(t, err)
   390  
   391  	definitions := specDoc.Spec().Definitions
   392  	k := "NotaWithMeta"
   393  	schema := definitions[k]
   394  	opts := opts()
   395  	genModel, err := makeGenDefinition(k, "models", schema, specDoc, opts)
   396  	require.NoError(t, err)
   397  
   398  	buf := bytes.NewBuffer(nil)
   399  	require.NoError(t, opts.templates.MustGet("model").Execute(buf, genModel))
   400  
   401  	ff, err := opts.LanguageOpts.FormatContent("nota_with_meta.go", buf.Bytes())
   402  	require.NoError(t, err)
   403  
   404  	res := string(ff)
   405  	assertInCode(t, "type NotaWithMeta map[string]NotaWithMetaAnon", res)
   406  	assertInCode(t, "type NotaWithMetaAnon struct {", res)
   407  	assertInCode(t, "Comment *string `json:\"comment\"`", res)
   408  	assertInCode(t, "Count int32 `json:\"count,omitempty\"`", res)
   409  }
   410  
   411  func TestGenerateModel_RunParameters(t *testing.T) {
   412  	specDoc, err := loads.Spec("../fixtures/codegen/todolist.models.yml")
   413  	require.NoError(t, err)
   414  
   415  	definitions := specDoc.Spec().Definitions
   416  	k := "RunParameters"
   417  	schema := definitions[k]
   418  	opts := opts()
   419  	genModel, err := makeGenDefinition(k, "models", schema, specDoc, opts)
   420  	require.NoError(t, err)
   421  
   422  	assert.False(t, genModel.IsAdditionalProperties)
   423  	assert.True(t, genModel.IsComplexObject)
   424  	assert.False(t, genModel.IsMap)
   425  	assert.False(t, genModel.IsAnonymous)
   426  	buf := bytes.NewBuffer(nil)
   427  	require.NoError(t, opts.templates.MustGet("model").Execute(buf, genModel))
   428  
   429  	res := buf.String()
   430  	assertInCode(t, "type "+k+" struct {", res)
   431  	assertInCode(t, "BranchName string `json:\"branch_name,omitempty\"`", res)
   432  	assertInCode(t, "CommitSha string `json:\"commit_sha,omitempty\"`", res)
   433  	assertInCode(t, "Refs interface{} `json:\"refs,omitempty\"`", res)
   434  }
   435  
   436  func TestGenerateModel_NotaWithName(t *testing.T) {
   437  	specDoc, err := loads.Spec("../fixtures/codegen/todolist.models.yml")
   438  	require.NoError(t, err)
   439  
   440  	definitions := specDoc.Spec().Definitions
   441  	k := "NotaWithName"
   442  	schema := definitions[k]
   443  	opts := opts()
   444  	genModel, err := makeGenDefinition(k, "models", schema, specDoc, opts)
   445  	require.NoError(t, err)
   446  
   447  	assert.True(t, genModel.IsAdditionalProperties)
   448  	assert.False(t, genModel.IsComplexObject)
   449  	assert.False(t, genModel.IsMap)
   450  	assert.False(t, genModel.IsAnonymous)
   451  	buf := bytes.NewBuffer(nil)
   452  	require.NoError(t, opts.templates.MustGet("model").Execute(buf, genModel))
   453  
   454  	res := buf.String()
   455  	assertInCode(t, "type "+k+" struct {", res)
   456  	assertInCode(t, k+" map[string]int32 `json:\"-\"`", res)
   457  	assertInCode(t, "Name *string `json:\"name\"`", res)
   458  	assertInCode(t, k+") UnmarshalJSON", res)
   459  	assertInCode(t, k+") MarshalJSON", res)
   460  	assertInCode(t, "json.Marshal(stage1)", res)
   461  	assertInCode(t, "stage1.Name = m.Name", res)
   462  	assertInCode(t, "json.Marshal(m."+k+")", res)
   463  	assertInCode(t, "json.Unmarshal(data, &stage1)", res)
   464  	assertInCode(t, "json.Unmarshal(data, &stage2)", res)
   465  	assertInCode(t, "json.Unmarshal(v, &toadd)", res)
   466  	assertInCode(t, "result[k] = toadd", res)
   467  	assertInCode(t, "m."+k+" = result", res)
   468  	for _, p := range genModel.Properties {
   469  		assertInCode(t, "delete(stage2, \""+p.Name+"\")", res)
   470  	}
   471  }
   472  
   473  func TestGenerateModel_NotaWithRefRegistry(t *testing.T) {
   474  	specDoc, err := loads.Spec("../fixtures/codegen/todolist.models.yml")
   475  	require.NoError(t, err)
   476  
   477  	definitions := specDoc.Spec().Definitions
   478  	k := "NotaWithRefRegistry"
   479  	schema := definitions[k]
   480  	opts := opts()
   481  	genModel, err := makeGenDefinition(k, "models", schema, specDoc, opts)
   482  	require.NoError(t, err)
   483  
   484  	buf := bytes.NewBuffer(nil)
   485  	require.NoError(t, opts.templates.MustGet("model").Execute(buf, genModel))
   486  
   487  	ff, err := opts.LanguageOpts.FormatContent("nota_with_ref_registry.go", buf.Bytes())
   488  	require.NoError(t, err)
   489  
   490  	assertInCode(t, "type "+k+" map[string]map[string]map[string]Notable", string(ff))
   491  }
   492  
   493  func TestGenerateModel_WithCustomTag(t *testing.T) {
   494  	specDoc, err := loads.Spec("../fixtures/codegen/todolist.models.yml")
   495  	require.NoError(t, err)
   496  
   497  	definitions := specDoc.Spec().Definitions
   498  	k := "WithCustomTag"
   499  	schema := definitions[k]
   500  	opts := opts()
   501  	genModel, err := makeGenDefinition(k, "models", schema, specDoc, opts)
   502  	require.NoError(t, err)
   503  
   504  	buf := bytes.NewBuffer(nil)
   505  	require.NoError(t, opts.templates.MustGet("model").Execute(buf, genModel))
   506  
   507  	assertInCode(t, "mytag:\"foo,bar\"", buf.String())
   508  }
   509  
   510  func TestGenerateModel_NotaWithMetaRegistry(t *testing.T) {
   511  	specDoc, err := loads.Spec("../fixtures/codegen/todolist.models.yml")
   512  	require.NoError(t, err)
   513  
   514  	definitions := specDoc.Spec().Definitions
   515  	k := "NotaWithMetaRegistry"
   516  	schema := definitions[k]
   517  	opts := opts()
   518  	genModel, err := makeGenDefinition(k, "models", schema, specDoc, opts)
   519  	require.NoError(t, err)
   520  
   521  	buf := bytes.NewBuffer(nil)
   522  	require.NoError(t, opts.templates.MustGet("model").Execute(buf, genModel))
   523  
   524  	ff, err := opts.LanguageOpts.FormatContent("nota_with_meta_registry.go", buf.Bytes())
   525  	require.NoError(t, err)
   526  
   527  	res := string(ff)
   528  	assertInCode(t, "type "+k+" map[string]map[string]map[string]NotaWithMetaRegistryAnon", res)
   529  	assertInCode(t, "type NotaWithMetaRegistryAnon struct {", res)
   530  	assertInCode(t, "Comment *string `json:\"comment\"`", res)
   531  	assertInCode(t, "Count int32 `json:\"count,omitempty\"`", res)
   532  }
   533  
   534  func TestGenerateModel_WithMap(t *testing.T) {
   535  	specDoc, err := loads.Spec("../fixtures/codegen/todolist.models.yml")
   536  	require.NoError(t, err)
   537  
   538  	definitions := specDoc.Spec().Definitions
   539  	schema := definitions["WithMap"]
   540  	opts := opts()
   541  	genModel, err := makeGenDefinition("WithMap", "models", schema, specDoc, opts)
   542  	require.NoError(t, err)
   543  
   544  	assert.False(t, genModel.HasAdditionalProperties)
   545  	prop := getDefinitionProperty(genModel, "data")
   546  	assert.True(t, prop.HasAdditionalProperties)
   547  	assert.True(t, prop.IsMap)
   548  	assert.False(t, prop.IsComplexObject)
   549  	buf := bytes.NewBuffer(nil)
   550  	require.NoError(t, templates.MustGet("model").Execute(buf, genModel))
   551  
   552  	res := buf.String()
   553  	assertInCode(t, "type WithMap struct {", res)
   554  	assertInCode(t, "Data map[string]string `json:\"data,omitempty\"`", res)
   555  }
   556  
   557  func TestGenerateModel_WithMapInterface(t *testing.T) {
   558  	specDoc, err := loads.Spec("../fixtures/codegen/todolist.models.yml")
   559  	require.NoError(t, err)
   560  
   561  	definitions := specDoc.Spec().Definitions
   562  	schema := definitions["WithMapInterface"]
   563  	opts := opts()
   564  	genModel, err := makeGenDefinition("WithMapInterface", "models", schema, specDoc, opts)
   565  	require.NoError(t, err)
   566  
   567  	assert.False(t, genModel.HasAdditionalProperties)
   568  	prop := getDefinitionProperty(genModel, "extraInfo")
   569  	assert.True(t, prop.HasAdditionalProperties)
   570  	assert.True(t, prop.IsMap)
   571  	assert.False(t, prop.IsComplexObject)
   572  	assert.Equal(t, "map[string]interface{}", prop.GoType)
   573  	assert.True(t, prop.Required)
   574  	assert.True(t, prop.HasValidations)
   575  
   576  	buf := bytes.NewBuffer(nil)
   577  	require.NoError(t, opts.templates.MustGet("model").Execute(buf, genModel))
   578  
   579  	res := buf.String()
   580  	assertInCode(t, "type WithMapInterface struct {", res)
   581  	assertInCode(t, "ExtraInfo map[string]interface{} `json:\"extraInfo\"`", res)
   582  }
   583  
   584  func TestGenerateModel_WithMapRef(t *testing.T) {
   585  	specDoc, err := loads.Spec("../fixtures/codegen/todolist.models.yml")
   586  	require.NoError(t, err)
   587  
   588  	definitions := specDoc.Spec().Definitions
   589  	k := "WithMapRef"
   590  	schema := definitions[k]
   591  	opts := opts()
   592  	genModel, err := makeGenDefinition(k, "models", schema, specDoc, opts)
   593  	require.NoError(t, err)
   594  
   595  	assert.False(t, genModel.HasAdditionalProperties)
   596  	prop := getDefinitionProperty(genModel, "data")
   597  	assert.True(t, prop.HasAdditionalProperties)
   598  	assert.True(t, prop.IsMap)
   599  	assert.False(t, prop.IsComplexObject)
   600  	buf := bytes.NewBuffer(nil)
   601  	require.NoError(t, opts.templates.MustGet("model").Execute(buf, genModel))
   602  
   603  	res := buf.String()
   604  	assertInCode(t, "type "+k+" struct {", res)
   605  	assertInCode(t, "Data map[string]Notable `json:\"data,omitempty\"`", res)
   606  }
   607  
   608  func TestGenerateModel_WithMapComplex(t *testing.T) {
   609  	specDoc, err := loads.Spec("../fixtures/codegen/todolist.models.yml")
   610  	require.NoError(t, err)
   611  
   612  	definitions := specDoc.Spec().Definitions
   613  	k := "WithMapComplex"
   614  	schema := definitions[k]
   615  	opts := opts()
   616  	genModel, err := makeGenDefinition(k, "models", schema, specDoc, opts)
   617  	require.NoError(t, err)
   618  
   619  	assert.False(t, genModel.HasAdditionalProperties)
   620  	prop := getDefinitionProperty(genModel, "data")
   621  	assert.True(t, prop.HasAdditionalProperties)
   622  	assert.True(t, prop.IsMap)
   623  	assert.False(t, prop.IsComplexObject)
   624  	buf := bytes.NewBuffer(nil)
   625  	require.NoError(t, opts.templates.MustGet("model").Execute(buf, genModel))
   626  
   627  	res := buf.String()
   628  	assertInCode(t, "type "+k+" struct {", res)
   629  	assertInCode(t, "Data map[string]"+k+"DataAnon `json:\"data,omitempty\"`", res)
   630  }
   631  
   632  func TestGenerateModel_WithMapRegistry(t *testing.T) {
   633  	specDoc, err := loads.Spec("../fixtures/codegen/todolist.models.yml")
   634  	require.NoError(t, err)
   635  
   636  	definitions := specDoc.Spec().Definitions
   637  	schema := definitions["WithMapRegistry"]
   638  	opts := opts()
   639  	genModel, err := makeGenDefinition("WithMap", "models", schema, specDoc, opts)
   640  	require.NoError(t, err)
   641  
   642  	assert.False(t, genModel.HasAdditionalProperties)
   643  	prop := getDefinitionProperty(genModel, "data")
   644  	assert.True(t, prop.HasAdditionalProperties)
   645  	assert.True(t, prop.IsMap)
   646  	assert.False(t, prop.IsComplexObject)
   647  	buf := bytes.NewBuffer(nil)
   648  	require.NoError(t, opts.templates.MustGet("model").Execute(buf, genModel))
   649  
   650  	res := buf.String()
   651  	assertInCode(t, "type WithMap struct {", res)
   652  	assertInCode(t, "Data map[string]map[string]map[string]string `json:\"data,omitempty\"`", res)
   653  }
   654  
   655  func TestGenerateModel_WithMapRegistryRef(t *testing.T) {
   656  	specDoc, err := loads.Spec("../fixtures/codegen/todolist.models.yml")
   657  	require.NoError(t, err)
   658  
   659  	definitions := specDoc.Spec().Definitions
   660  	k := "WithMapRegistryRef"
   661  	schema := definitions[k]
   662  	opts := opts()
   663  	genModel, err := makeGenDefinition(k, "models", schema, specDoc, opts)
   664  	require.NoError(t, err)
   665  
   666  	assert.False(t, genModel.HasAdditionalProperties)
   667  	prop := getDefinitionProperty(genModel, "data")
   668  	assert.True(t, prop.HasAdditionalProperties)
   669  	assert.True(t, prop.IsMap)
   670  	assert.False(t, prop.IsComplexObject)
   671  	buf := bytes.NewBuffer(nil)
   672  	require.NoError(t, opts.templates.MustGet("model").Execute(buf, genModel))
   673  
   674  	res := buf.String()
   675  	assertInCode(t, "type "+k+" struct {", res)
   676  	assertInCode(t, "Data map[string]map[string]map[string]Notable `json:\"data,omitempty\"`", res)
   677  }
   678  
   679  func TestGenerateModel_WithMapComplexRegistry(t *testing.T) {
   680  	specDoc, err := loads.Spec("../fixtures/codegen/todolist.models.yml")
   681  	require.NoError(t, err)
   682  
   683  	definitions := specDoc.Spec().Definitions
   684  	k := "WithMapComplexRegistry"
   685  	schema := definitions[k]
   686  	opts := opts()
   687  	genModel, err := makeGenDefinition(k, "models", schema, specDoc, opts)
   688  	require.NoError(t, err)
   689  
   690  	assert.False(t, genModel.HasAdditionalProperties)
   691  	prop := getDefinitionProperty(genModel, "data")
   692  	assert.True(t, prop.HasAdditionalProperties)
   693  	assert.True(t, prop.IsMap)
   694  	assert.False(t, prop.IsComplexObject)
   695  	buf := bytes.NewBuffer(nil)
   696  	require.NoError(t, opts.templates.MustGet("model").Execute(buf, genModel))
   697  
   698  	res := buf.String()
   699  	assertInCode(t, "type "+k+" struct {", res)
   700  	assertInCode(t, "Data map[string]map[string]map[string]"+k+"DataAnon `json:\"data,omitempty\"`", res)
   701  }
   702  
   703  func TestGenerateModel_WithAdditional(t *testing.T) {
   704  	specDoc, err := loads.Spec("../fixtures/codegen/todolist.models.yml")
   705  	require.NoError(t, err)
   706  
   707  	definitions := specDoc.Spec().Definitions
   708  	k := "WithAdditional"
   709  	schema := definitions[k]
   710  	opts := opts()
   711  	genModel, err := makeGenDefinition(k, "models", schema, specDoc, opts)
   712  	require.NoError(t, err)
   713  	require.NotEmpty(t, genModel.ExtraSchemas)
   714  
   715  	assert.False(t, genModel.HasAdditionalProperties)
   716  	assert.False(t, genModel.IsMap)
   717  	assert.False(t, genModel.IsAdditionalProperties)
   718  	assert.True(t, genModel.IsComplexObject)
   719  
   720  	sch := genModel.ExtraSchemas[0]
   721  	assert.True(t, sch.HasAdditionalProperties)
   722  	assert.False(t, sch.IsMap)
   723  	assert.True(t, sch.IsAdditionalProperties)
   724  	assert.False(t, sch.IsComplexObject)
   725  
   726  	require.NotNil(t, sch.AdditionalProperties)
   727  
   728  	prop := findProperty(genModel.Properties, "data")
   729  	assert.False(t, prop.HasAdditionalProperties)
   730  	assert.False(t, prop.IsMap)
   731  	assert.False(t, prop.IsAdditionalProperties)
   732  	assert.True(t, prop.IsComplexObject)
   733  	buf := bytes.NewBuffer(nil)
   734  	require.NoError(t, opts.templates.MustGet("model").Execute(buf, genModel))
   735  
   736  	res := buf.String()
   737  	assertInCode(t, "type "+k+" struct {", res)
   738  	assertInCode(t, "Data *"+k+"Data `json:\"data,omitempty\"`", res)
   739  	assertInCode(t, "type "+k+"Data struct {", res)
   740  	assertInCode(t, k+"Data map[string]string `json:\"-\"`", res)
   741  	assertInCode(t, "Name *string `json:\"name\"`", res)
   742  	assertInCode(t, k+"Data) UnmarshalJSON", res)
   743  	assertInCode(t, k+"Data) MarshalJSON", res)
   744  	assertInCode(t, "json.Marshal(stage1)", res)
   745  	assertInCode(t, "stage1.Name = m.Name", res)
   746  	assertInCode(t, "json.Marshal(m."+k+"Data)", res)
   747  	assertInCode(t, "json.Unmarshal(data, &stage1)", res)
   748  	assertInCode(t, "json.Unmarshal(data, &stage2)", res)
   749  	assertInCode(t, "json.Unmarshal(v, &toadd)", res)
   750  	assertInCode(t, "result[k] = toadd", res)
   751  	assertInCode(t, "m."+k+"Data = result", res)
   752  
   753  	for _, p := range sch.Properties {
   754  		assertInCode(t, "delete(stage2, \""+p.Name+"\")", res)
   755  	}
   756  }
   757  
   758  func TestGenerateModel_JustRef(t *testing.T) {
   759  	tt := templateTest{t, templates.MustGet("model").Lookup("schema")}
   760  	specDoc, err := loads.Spec("../fixtures/codegen/todolist.models.yml")
   761  	require.NoError(t, err)
   762  
   763  	definitions := specDoc.Spec().Definitions
   764  	schema := definitions["JustRef"]
   765  	opts := opts()
   766  	genModel, err := makeGenDefinition("JustRef", "models", schema, specDoc, opts)
   767  	require.NoError(t, err)
   768  
   769  	assert.NotEmpty(t, genModel.AllOf)
   770  	assert.True(t, genModel.IsComplexObject)
   771  	assert.Equal(t, "JustRef", genModel.Name)
   772  	assert.Equal(t, "JustRef", genModel.GoType)
   773  	buf := bytes.NewBuffer(nil)
   774  	require.NoError(t, tt.template.Execute(buf, genModel))
   775  
   776  	res := buf.String()
   777  	assertInCode(t, "type JustRef struct {", res)
   778  	assertInCode(t, "Notable", res)
   779  }
   780  
   781  func TestGenerateModel_WithRef(t *testing.T) {
   782  	tt := templateTest{t, templates.MustGet("model").Lookup("schema")}
   783  	specDoc, err := loads.Spec("../fixtures/codegen/todolist.models.yml")
   784  	require.NoError(t, err)
   785  
   786  	definitions := specDoc.Spec().Definitions
   787  	schema := definitions["WithRef"]
   788  	opts := opts()
   789  	genModel, err := makeGenDefinition("WithRef", "models", schema, specDoc, opts)
   790  	require.NoError(t, err)
   791  
   792  	assert.True(t, genModel.IsComplexObject)
   793  	assert.Equal(t, "WithRef", genModel.Name)
   794  	assert.Equal(t, "WithRef", genModel.GoType)
   795  	buf := bytes.NewBuffer(nil)
   796  	require.NoError(t, tt.template.Execute(buf, genModel))
   797  
   798  	res := buf.String()
   799  	assertInCode(t, "type WithRef struct {", res)
   800  	assertInCode(t, "Notes *Notable `json:\"notes,omitempty\"`", res)
   801  }
   802  
   803  func TestGenerateModel_WithNullableRef(t *testing.T) {
   804  	tt := templateTest{t, templates.MustGet("model").Lookup("schema")}
   805  	specDoc, err := loads.Spec("../fixtures/codegen/todolist.models.yml")
   806  	require.NoError(t, err)
   807  
   808  	definitions := specDoc.Spec().Definitions
   809  	schema := definitions["WithNullableRef"]
   810  	opts := opts()
   811  	genModel, err := makeGenDefinition("WithNullableRef", "models", schema, specDoc, opts)
   812  	require.NoError(t, err)
   813  
   814  	assert.True(t, genModel.IsComplexObject)
   815  	assert.Equal(t, "WithNullableRef", genModel.Name)
   816  	assert.Equal(t, "WithNullableRef", genModel.GoType)
   817  	prop := getDefinitionProperty(genModel, "notes")
   818  	assert.True(t, prop.IsNullable)
   819  	assert.True(t, prop.IsComplexObject)
   820  	buf := bytes.NewBuffer(nil)
   821  	require.NoError(t, tt.template.Execute(buf, genModel))
   822  
   823  	res := buf.String()
   824  	assertInCode(t, "type WithNullableRef struct {", res)
   825  	assertInCode(t, "Notes *Notable `json:\"notes,omitempty\"`", res)
   826  }
   827  
   828  func TestGenerateModel_Scores(t *testing.T) {
   829  	specDoc, err := loads.Spec("../fixtures/codegen/todolist.models.yml")
   830  	require.NoError(t, err)
   831  
   832  	definitions := specDoc.Spec().Definitions
   833  	k := "Scores"
   834  	schema := definitions[k]
   835  	opts := opts()
   836  	genModel, err := makeGenDefinition(k, "models", schema, specDoc, opts)
   837  	require.NoError(t, err)
   838  
   839  	buf := bytes.NewBuffer(nil)
   840  	require.NoError(t, opts.templates.MustGet("model").Execute(buf, genModel))
   841  
   842  	ff, err := opts.LanguageOpts.FormatContent("scores.go", buf.Bytes())
   843  	require.NoError(t, err)
   844  
   845  	assertInCode(t, "type Scores []float32", string(ff))
   846  }
   847  
   848  func TestGenerateModel_JaggedScores(t *testing.T) {
   849  	specDoc, err := loads.Spec("../fixtures/codegen/todolist.models.yml")
   850  	require.NoError(t, err)
   851  
   852  	definitions := specDoc.Spec().Definitions
   853  	k := "JaggedScores"
   854  	schema := definitions[k]
   855  	opts := opts()
   856  	genModel, err := makeGenDefinition(k, "models", schema, specDoc, opts)
   857  	require.NoError(t, err)
   858  
   859  	buf := bytes.NewBuffer(nil)
   860  	require.NoError(t, opts.templates.MustGet("model").Execute(buf, genModel))
   861  
   862  	ff, err := opts.LanguageOpts.FormatContent("jagged_scores.go", buf.Bytes())
   863  	require.NoError(t, err)
   864  
   865  	assertInCode(t, "type JaggedScores [][][]float32", string(ff))
   866  }
   867  
   868  func TestGenerateModel_Notables(t *testing.T) {
   869  	specDoc, err := loads.Spec("../fixtures/codegen/todolist.models.yml")
   870  	require.NoError(t, err)
   871  
   872  	definitions := specDoc.Spec().Definitions
   873  	k := "Notables"
   874  	schema := definitions[k]
   875  	opts := opts()
   876  	genModel, err := makeGenDefinition(k, "models", schema, specDoc, opts)
   877  	require.NoError(t, err)
   878  	require.Equal(t, "[]*Notable", genModel.GoType)
   879  
   880  	buf := bytes.NewBuffer(nil)
   881  	require.NoError(t, opts.templates.MustGet("model").Execute(buf, genModel))
   882  	require.NoError(t, err)
   883  
   884  	ff, err := opts.LanguageOpts.FormatContent("notables.go", buf.Bytes())
   885  	require.NoError(t, err)
   886  
   887  	res := string(ff)
   888  	assertInCode(t, "type Notables []*Notable", res)
   889  }
   890  
   891  func TestGenerateModel_Notablix(t *testing.T) {
   892  	specDoc, err := loads.Spec("../fixtures/codegen/todolist.models.yml")
   893  	require.NoError(t, err)
   894  
   895  	definitions := specDoc.Spec().Definitions
   896  	k := "Notablix"
   897  	schema := definitions[k]
   898  	opts := opts()
   899  	genModel, err := makeGenDefinition(k, "models", schema, specDoc, opts)
   900  	require.NoError(t, err)
   901  
   902  	buf := bytes.NewBuffer(nil)
   903  	require.NoError(t, opts.templates.MustGet("model").Execute(buf, genModel))
   904  
   905  	ff, err := opts.LanguageOpts.FormatContent("notablix.go", buf.Bytes())
   906  	require.NoError(t, err)
   907  
   908  	res := string(ff)
   909  	assertInCode(t, "type Notablix [][][]*Notable", res)
   910  }
   911  
   912  func TestGenerateModel_Stats(t *testing.T) {
   913  	specDoc, err := loads.Spec("../fixtures/codegen/todolist.models.yml")
   914  	require.NoError(t, err)
   915  
   916  	definitions := specDoc.Spec().Definitions
   917  	k := "Stats"
   918  	schema := definitions[k]
   919  	opts := opts()
   920  	genModel, err := makeGenDefinition(k, "models", schema, specDoc, opts)
   921  	require.NoError(t, err)
   922  
   923  	buf := bytes.NewBuffer(nil)
   924  	require.NoError(t, opts.templates.MustGet("model").Execute(buf, genModel))
   925  
   926  	ff, err := opts.LanguageOpts.FormatContent("stats.go", buf.Bytes())
   927  	require.NoError(t, err)
   928  
   929  	res := string(ff)
   930  	assertInCode(t, "type Stats []*StatsItems0", res)
   931  	assertInCode(t, "type StatsItems0 struct {", res)
   932  	assertInCode(t, "Points []int64 `json:\"points\"`", res)
   933  }
   934  
   935  func TestGenerateModel_Statix(t *testing.T) {
   936  	specDoc, err := loads.Spec("../fixtures/codegen/todolist.models.yml")
   937  	require.NoError(t, err)
   938  
   939  	definitions := specDoc.Spec().Definitions
   940  	k := "Statix"
   941  	schema := definitions[k]
   942  	opts := opts()
   943  	genModel, err := makeGenDefinition(k, "models", schema, specDoc, opts)
   944  	require.NoError(t, err)
   945  
   946  	buf := bytes.NewBuffer(nil)
   947  	require.NoError(t, opts.templates.MustGet("model").Execute(buf, genModel))
   948  
   949  	ff, err := opts.LanguageOpts.FormatContent("statix.go", buf.Bytes())
   950  	require.NoError(t, err)
   951  
   952  	res := string(ff)
   953  	assertInCode(t, "type Statix [][][]*StatixItems0", res)
   954  	assertInCode(t, "type StatixItems0 struct {", res)
   955  	assertInCode(t, "Points []int64 `json:\"points\"`", res)
   956  }
   957  
   958  func TestGenerateModel_WithItems(t *testing.T) {
   959  	specDoc, err := loads.Spec("../fixtures/codegen/todolist.models.yml")
   960  	require.NoError(t, err)
   961  
   962  	definitions := specDoc.Spec().Definitions
   963  	schema := definitions["WithItems"]
   964  	opts := opts()
   965  	tt := templateTest{t, opts.templates.MustGet("model").Lookup("schema")}
   966  
   967  	genModel, err := makeGenDefinition("WithItems", "models", schema, specDoc, opts)
   968  	require.NoError(t, err)
   969  
   970  	assert.Nil(t, genModel.Items)
   971  	assert.True(t, genModel.IsComplexObject)
   972  	prop := getDefinitionProperty(genModel, "tags")
   973  
   974  	assert.NotNil(t, prop.Items)
   975  	assert.True(t, prop.IsArray)
   976  	assert.False(t, prop.IsComplexObject)
   977  
   978  	buf := bytes.NewBuffer(nil)
   979  	require.NoError(t, tt.template.Execute(buf, genModel))
   980  
   981  	res := buf.String()
   982  	assertInCode(t, "type WithItems struct {", res)
   983  	assertInCode(t, "Tags []string `json:\"tags\"`", res)
   984  }
   985  
   986  func TestGenerateModel_WithComplexItems(t *testing.T) {
   987  	specDoc, err := loads.Spec("../fixtures/codegen/todolist.models.yml")
   988  	require.NoError(t, err)
   989  
   990  	definitions := specDoc.Spec().Definitions
   991  	k := "WithComplexItems"
   992  	schema := definitions[k]
   993  	opts := opts()
   994  	genModel, err := makeGenDefinition(k, "models", schema, specDoc, opts)
   995  	require.NoError(t, err)
   996  
   997  	assert.Nil(t, genModel.Items)
   998  	assert.True(t, genModel.IsComplexObject)
   999  	prop := getDefinitionProperty(genModel, "tags")
  1000  	assert.NotNil(t, prop.Items)
  1001  	assert.True(t, prop.IsArray)
  1002  	assert.False(t, prop.IsComplexObject)
  1003  	buf := bytes.NewBuffer(nil)
  1004  
  1005  	require.NoError(t, opts.templates.MustGet("model").Execute(buf, genModel))
  1006  
  1007  	b, err := opts.LanguageOpts.FormatContent("with_complex_items.go", buf.Bytes())
  1008  	require.NoError(t, err)
  1009  
  1010  	res := string(b)
  1011  	assertInCode(t, "type WithComplexItems struct {", res)
  1012  	assertInCode(t, "type WithComplexItemsTagsItems0 struct {", res)
  1013  	assertInCode(t, "Tags []*WithComplexItemsTagsItems0 `json:\"tags\"`", res)
  1014  }
  1015  
  1016  func TestGenerateModel_WithItemsAndAdditional(t *testing.T) {
  1017  	specDoc, err := loads.Spec("../fixtures/codegen/todolist.models.yml")
  1018  	require.NoError(t, err)
  1019  
  1020  	definitions := specDoc.Spec().Definitions
  1021  	k := "WithItemsAndAdditional"
  1022  	schema := definitions[k]
  1023  	opts := opts()
  1024  	genModel, err := makeGenDefinition(k, "models", schema, specDoc, opts)
  1025  	require.NoError(t, err)
  1026  
  1027  	assert.Nil(t, genModel.Items)
  1028  	assert.True(t, genModel.IsComplexObject)
  1029  	prop := getDefinitionProperty(genModel, "tags")
  1030  	assert.True(t, prop.IsComplexObject)
  1031  	buf := bytes.NewBuffer(nil)
  1032  	require.NoError(t, opts.templates.MustGet("model").Execute(buf, genModel))
  1033  
  1034  	b, err := opts.LanguageOpts.FormatContent("with_complex_items.go", buf.Bytes())
  1035  	require.NoError(t, err)
  1036  
  1037  	res := string(b)
  1038  	assertInCode(t, "type "+k+" struct {", res)
  1039  	assertInCode(t, "type "+k+"TagsTuple0 struct {", res)
  1040  	// this would fail if it accepts additionalItems because it would come out as []interface{}
  1041  	assertInCode(t, "Tags *"+k+"TagsTuple0 `json:\"tags,omitempty\"`", res)
  1042  	assertInCode(t, "P0 *string `json:\"-\"`", res)
  1043  	assertInCode(t, k+"TagsTuple0Items []interface{} `json:\"-\"`", res)
  1044  }
  1045  
  1046  func TestGenerateModel_WithItemsAndAdditional2(t *testing.T) {
  1047  	specDoc, err := loads.Spec("../fixtures/codegen/todolist.models.yml")
  1048  	require.NoError(t, err)
  1049  
  1050  	definitions := specDoc.Spec().Definitions
  1051  	k := "WithItemsAndAdditional2"
  1052  	schema := definitions[k]
  1053  	opts := opts()
  1054  	genModel, err := makeGenDefinition(k, "models", schema, specDoc, opts)
  1055  	require.NoError(t, err)
  1056  
  1057  	assert.Nil(t, genModel.Items)
  1058  	assert.True(t, genModel.IsComplexObject)
  1059  	prop := getDefinitionProperty(genModel, "tags")
  1060  	assert.True(t, prop.IsComplexObject)
  1061  	buf := bytes.NewBuffer(nil)
  1062  	require.NoError(t, opts.templates.MustGet("model").Execute(buf, genModel))
  1063  
  1064  	b, err := opts.LanguageOpts.FormatContent("with_complex_items.go", buf.Bytes())
  1065  	require.NoError(t, err)
  1066  
  1067  	res := string(b)
  1068  	assertInCode(t, "type "+k+" struct {", res)
  1069  	assertInCode(t, "type "+k+"TagsTuple0 struct {", res)
  1070  	// this would fail if it accepts additionalItems because it would come out as []interface{}
  1071  	assertInCode(t, "P0 *string `json:\"-\"`", res)
  1072  	assertInCode(t, "Tags *"+k+"TagsTuple0 `json:\"tags,omitempty\"`", res)
  1073  	assertInCode(t, k+"TagsTuple0Items []int32 `json:\"-\"`", res)
  1074  }
  1075  
  1076  func TestGenerateModel_WithComplexAdditional(t *testing.T) {
  1077  	specDoc, err := loads.Spec("../fixtures/codegen/todolist.models.yml")
  1078  	require.NoError(t, err)
  1079  
  1080  	definitions := specDoc.Spec().Definitions
  1081  	k := "WithComplexAdditional"
  1082  	schema := definitions[k]
  1083  	opts := opts()
  1084  	genModel, err := makeGenDefinition(k, "models", schema, specDoc, opts)
  1085  	require.NoError(t, err)
  1086  
  1087  	assert.Nil(t, genModel.Items)
  1088  	assert.True(t, genModel.IsComplexObject)
  1089  	prop := getDefinitionProperty(genModel, "tags")
  1090  	assert.True(t, prop.IsComplexObject)
  1091  	buf := bytes.NewBuffer(nil)
  1092  	require.NoError(t, opts.templates.MustGet("model").Execute(buf, genModel))
  1093  
  1094  	b, err := opts.LanguageOpts.FormatContent("with_complex_additional.go", buf.Bytes())
  1095  	require.NoError(t, err)
  1096  
  1097  	res := string(b)
  1098  	assertInCode(t, "type WithComplexAdditional struct {", res)
  1099  	assertInCode(t, "type WithComplexAdditionalTagsTuple0 struct {", res)
  1100  	assertInCode(t, "Tags *WithComplexAdditionalTagsTuple0 `json:\"tags,omitempty\"`", res)
  1101  	assertInCode(t, "P0 *string `json:\"-\"`", res)
  1102  	assertInCode(t, "WithComplexAdditionalTagsTuple0Items []*WithComplexAdditionalTagsItems `json:\"-\"`", res)
  1103  }
  1104  
  1105  func TestGenerateModel_SimpleTuple(t *testing.T) {
  1106  	specDoc, err := loads.Spec("../fixtures/codegen/todolist.models.yml")
  1107  	require.NoError(t, err)
  1108  
  1109  	definitions := specDoc.Spec().Definitions
  1110  	k := "SimpleTuple"
  1111  	schema := definitions[k]
  1112  	opts := opts()
  1113  
  1114  	tt := templateTest{t, opts.templates.MustGet("model")}
  1115  	genModel, err := makeGenDefinition(k, "models", schema, specDoc, opts)
  1116  	require.NoError(t, err)
  1117  	require.Len(t, genModel.ExtraSchemas, 1)
  1118  
  1119  	// NOTE: with PR#1592, an extra schema is added here because of the allOf tuple element.
  1120  	// This uncovers another issue with special AllOfs (e.g. allOf [ ..., x-nullable:true ])
  1121  	// TODO(fredbi): fix liftSpecialAllOf() to revert to: assert.Empty(t, genModel.ExtraSchemas)
  1122  	assert.True(t, genModel.IsTuple)
  1123  	assert.False(t, genModel.IsComplexObject)
  1124  	assert.False(t, genModel.IsArray)
  1125  	assert.False(t, genModel.IsAnonymous)
  1126  	assert.Equal(t, k, genModel.Name)
  1127  	assert.Equal(t, k, genModel.GoType)
  1128  	assert.Len(t, genModel.Properties, 5)
  1129  	buf := bytes.NewBuffer(nil)
  1130  	require.NoError(t, tt.template.Execute(buf, genModel))
  1131  
  1132  	res := buf.String()
  1133  	assertInCode(t, "swagger:model "+k, res)
  1134  	assertInCode(t, "type "+k+" struct {", res)
  1135  	assertInCode(t, "P0 *int64 `json:\"-\"`", res)
  1136  	assertInCode(t, "P1 *string `json:\"-\"`", res)
  1137  	assertInCode(t, "P2 *strfmt.DateTime `json:\"-\"`", res)
  1138  	assertInCode(t, "P3 *Notable `json:\"-\"`", res)
  1139  	// NOTE: with PR#1592, an extra schema is added here because of the allOf tuple element.
  1140  	// This uncovers another issue with special AllOfs (e.g. allOf [ ..., x-nullable:true ])
  1141  	// TODO(fredbi): fix liftSpecialAllOf() to revert to: assert.Empty(t, genModel.ExtraSchemas)
  1142  	// assertInCode(t, "P4 *Notable `json:\"-\"`", res)
  1143  	assertInCode(t, "P4 *SimpleTupleItems4 `json:\"-\"`", res)
  1144  	assertInCode(t, k+") UnmarshalJSON", res)
  1145  	assertInCode(t, k+") MarshalJSON", res)
  1146  	assertInCode(t, "json.Marshal(data)", res)
  1147  	assert.NotRegexp(t, regexp.MustCompile("lastIndex"), res)
  1148  
  1149  	for i, p := range genModel.Properties {
  1150  		m := "m.P" + strconv.Itoa(i)
  1151  		r := "&dataP" + strconv.Itoa(i)
  1152  		var rr string
  1153  		if !p.IsNullable {
  1154  			rr = "dataP" + strconv.Itoa(i)
  1155  		} else {
  1156  			rr = r
  1157  		}
  1158  		assertInCode(t, fmt.Sprintf("buf = bytes.NewBuffer(stage1[%d])", i), res)
  1159  		assertInCode(t, fmt.Sprintf("dec.Decode(%s)", r), res)
  1160  		assertInCode(t, "P"+strconv.Itoa(i)+",", res)
  1161  		assertInCode(t, fmt.Sprintf("%s = %s", m, rr), res)
  1162  	}
  1163  }
  1164  
  1165  func TestGenerateModel_TupleWithExtra(t *testing.T) {
  1166  	specDoc, err := loads.Spec("../fixtures/codegen/todolist.models.yml")
  1167  	require.NoError(t, err)
  1168  
  1169  	definitions := specDoc.Spec().Definitions
  1170  	k := "TupleWithExtra"
  1171  	schema := definitions[k]
  1172  	opts := opts()
  1173  	genModel, err := makeGenDefinition(k, "models", schema, specDoc, opts)
  1174  	require.NoError(t, err)
  1175  	require.Empty(t, genModel.ExtraSchemas)
  1176  
  1177  	assert.True(t, genModel.IsTuple)
  1178  	assert.False(t, genModel.IsComplexObject)
  1179  	assert.False(t, genModel.IsArray)
  1180  	assert.False(t, genModel.IsAnonymous)
  1181  	assert.True(t, genModel.HasAdditionalItems)
  1182  	assert.NotNil(t, genModel.AdditionalItems)
  1183  	assert.Equal(t, k, genModel.Name)
  1184  	assert.Equal(t, k, genModel.GoType)
  1185  	assert.Len(t, genModel.Properties, 4)
  1186  	buf := bytes.NewBuffer(nil)
  1187  	require.NoError(t, opts.templates.MustGet("model").Execute(buf, genModel))
  1188  
  1189  	ff, err := opts.LanguageOpts.FormatContent("tuple_with_extra.go", buf.Bytes())
  1190  	require.NoError(t, err)
  1191  
  1192  	res := string(ff)
  1193  	assertInCode(t, "swagger:model "+k, res)
  1194  	assertInCode(t, "type "+k+" struct {", res)
  1195  	assertInCode(t, "P0 *int64 `json:\"-\"`", res)
  1196  	assertInCode(t, "P1 *string `json:\"-\"`", res)
  1197  	assertInCode(t, "P2 *strfmt.DateTime `json:\"-\"`", res)
  1198  	assertInCode(t, "P3 *Notable `json:\"-\"`", res)
  1199  	assertInCode(t, k+"Items []float64 `json:\"-\"`", res)
  1200  	assertInCode(t, k+") UnmarshalJSON", res)
  1201  	assertInCode(t, k+") MarshalJSON", res)
  1202  
  1203  	for i, p := range genModel.Properties {
  1204  		m := "m.P" + strconv.Itoa(i)
  1205  		r := "&dataP" + strconv.Itoa(i)
  1206  		var rr string
  1207  		if !p.IsNullable {
  1208  			rr = "dataP" + strconv.Itoa(i)
  1209  		} else {
  1210  			rr = r
  1211  		}
  1212  		assertInCode(t, fmt.Sprintf("lastIndex = %d", i), res)
  1213  		assertInCode(t, fmt.Sprintf("buf = bytes.NewBuffer(stage1[%d])", i), res)
  1214  		assertInCode(t, "dec := json.NewDecoder(buf)", res)
  1215  		assertInCode(t, fmt.Sprintf("dec.Decode(%s)", r), res)
  1216  		assertInCode(t, "P"+strconv.Itoa(i)+",", res)
  1217  		assertInCode(t, fmt.Sprintf("%s = %s", m, rr), res)
  1218  	}
  1219  
  1220  	assertInCode(t, "var lastIndex int", res)
  1221  	assertInCode(t, "var toadd float64", res)
  1222  	assertInCode(t, "for _, val := range stage1[lastIndex+1:]", res)
  1223  	assertInCode(t, "buf = bytes.NewBuffer(val)", res)
  1224  	assertInCode(t, "dec := json.NewDecoder(buf)", res)
  1225  	assertInCode(t, "dec.Decode(&toadd)", res)
  1226  	assertInCode(t, "json.Marshal(data)", res)
  1227  	assertInCode(t, "for _, v := range m."+k+"Items", res)
  1228  }
  1229  
  1230  func TestGenerateModel_TupleWithComplex(t *testing.T) {
  1231  	specDoc, err := loads.Spec("../fixtures/codegen/todolist.models.yml")
  1232  	require.NoError(t, err)
  1233  
  1234  	definitions := specDoc.Spec().Definitions
  1235  	k := "TupleWithComplex"
  1236  	schema := definitions[k]
  1237  	opts := opts()
  1238  	genModel, err := makeGenDefinition(k, "models", schema, specDoc, opts)
  1239  	require.NoError(t, err)
  1240  
  1241  	assert.True(t, genModel.IsTuple)
  1242  	assert.False(t, genModel.IsComplexObject)
  1243  	assert.False(t, genModel.IsArray)
  1244  	assert.False(t, genModel.IsAnonymous)
  1245  	assert.True(t, genModel.HasAdditionalItems)
  1246  	assert.NotNil(t, genModel.AdditionalItems)
  1247  	assert.Equal(t, k, genModel.Name)
  1248  	assert.Equal(t, k, genModel.GoType)
  1249  	assert.Len(t, genModel.Properties, 4)
  1250  	buf := bytes.NewBuffer(nil)
  1251  	require.NoError(t, opts.templates.MustGet("model").Execute(buf, genModel))
  1252  
  1253  	ff, err := opts.LanguageOpts.FormatContent("tuple_with_extra.go", buf.Bytes())
  1254  	require.NoError(t, err)
  1255  
  1256  	res := string(ff)
  1257  	assertInCode(t, "swagger:model "+k, res)
  1258  	assertInCode(t, "type "+k+" struct {", res)
  1259  	assertInCode(t, "P0 *int64 `json:\"-\"`", res)
  1260  	assertInCode(t, "P1 *string `json:\"-\"`", res)
  1261  	assertInCode(t, "P2 *strfmt.DateTime `json:\"-\"`", res)
  1262  	assertInCode(t, "P3 *Notable `json:\"-\"`", res)
  1263  	assertInCode(t, k+"Items []*TupleWithComplexItems `json:\"-\"`", res)
  1264  	assertInCode(t, k+") UnmarshalJSON", res)
  1265  	assertInCode(t, k+") MarshalJSON", res)
  1266  
  1267  	for i, p := range genModel.Properties {
  1268  		m := "m.P" + strconv.Itoa(i)
  1269  		r := "&dataP" + strconv.Itoa(i)
  1270  		var rr string
  1271  		if !p.IsNullable {
  1272  			rr = "dataP" + strconv.Itoa(i)
  1273  		} else {
  1274  			rr = r
  1275  		}
  1276  		assertInCode(t, fmt.Sprintf("lastIndex = %d", i), res)
  1277  		assertInCode(t, fmt.Sprintf("buf = bytes.NewBuffer(stage1[%d])", i), res)
  1278  		assertInCode(t, "dec := json.NewDecoder(buf)", res)
  1279  		assertInCode(t, fmt.Sprintf("dec.Decode(%s)", r), res)
  1280  		assertInCode(t, "P"+strconv.Itoa(i)+",", res)
  1281  		assertInCode(t, fmt.Sprintf("%s = %s", m, rr), res)
  1282  	}
  1283  
  1284  	assertInCode(t, "var lastIndex int", res)
  1285  	assertInCode(t, "var toadd *TupleWithComplexItems", res)
  1286  	assertInCode(t, "for _, val := range stage1[lastIndex+1:]", res)
  1287  	assertInCode(t, "buf = bytes.NewBuffer(val)", res)
  1288  	assertInCode(t, "dec := json.NewDecoder(buf)", res)
  1289  	assertInCode(t, "dec.Decode(toadd)", res)
  1290  	assertInCode(t, "json.Marshal(data)", res)
  1291  	assertInCode(t, "for _, v := range m."+k+"Items", res)
  1292  }
  1293  
  1294  func TestGenerateModel_WithTuple(t *testing.T) {
  1295  	specDoc, err := loads.Spec("../fixtures/codegen/todolist.models.yml")
  1296  	require.NoError(t, err)
  1297  
  1298  	definitions := specDoc.Spec().Definitions
  1299  	k := "WithTuple"
  1300  	schema := definitions[k]
  1301  	opts := opts()
  1302  	genModel, err := makeGenDefinition(k, "models", schema, specDoc, opts)
  1303  	require.NoError(t, err)
  1304  	require.NotEmpty(t, genModel.ExtraSchemas)
  1305  	require.NotEmpty(t, genModel.Properties)
  1306  
  1307  	assert.False(t, genModel.IsTuple)
  1308  	assert.True(t, genModel.IsComplexObject)
  1309  	assert.False(t, genModel.IsArray)
  1310  	assert.False(t, genModel.IsAnonymous)
  1311  
  1312  	sch := genModel.ExtraSchemas[0]
  1313  	assert.True(t, sch.IsTuple)
  1314  	assert.False(t, sch.IsComplexObject)
  1315  	assert.False(t, sch.IsArray)
  1316  	assert.False(t, sch.IsAnonymous)
  1317  	assert.Equal(t, k+"FlagsTuple0", sch.Name)
  1318  	assert.False(t, sch.HasAdditionalItems)
  1319  	assert.Nil(t, sch.AdditionalItems)
  1320  
  1321  	prop := genModel.Properties[0]
  1322  	assert.False(t, genModel.IsTuple)
  1323  	assert.True(t, genModel.IsComplexObject)
  1324  	assert.False(t, prop.IsArray)
  1325  	assert.False(t, prop.IsAnonymous)
  1326  	assert.Equal(t, k+"FlagsTuple0", prop.GoType)
  1327  	assert.Equal(t, "flags", prop.Name)
  1328  	buf := bytes.NewBuffer(nil)
  1329  	require.NoError(t, opts.templates.MustGet("model").Execute(buf, genModel))
  1330  
  1331  	ff, err := opts.LanguageOpts.FormatContent("with_tuple.go", buf.Bytes())
  1332  	require.NoError(t, err)
  1333  
  1334  	res := string(ff)
  1335  	assertInCode(t, "swagger:model "+k+"Flags", res)
  1336  	assertInCode(t, "type "+k+"FlagsTuple0 struct {", res)
  1337  	assertInCode(t, "P0 *int64 `json:\"-\"`", res)
  1338  	assertInCode(t, "P1 *string `json:\"-\"`", res)
  1339  	assertInCode(t, k+"FlagsTuple0) UnmarshalJSON", res)
  1340  	assertInCode(t, k+"FlagsTuple0) MarshalJSON", res)
  1341  	assertInCode(t, "json.Marshal(data)", res)
  1342  	assert.NotRegexp(t, regexp.MustCompile("lastIndex"), res)
  1343  
  1344  	for i, p := range sch.Properties {
  1345  		m := "m.P" + strconv.Itoa(i)
  1346  		r := "&dataP" + strconv.Itoa(i)
  1347  		var rr string
  1348  		if !p.IsNullable {
  1349  			rr = "dataP" + strconv.Itoa(i)
  1350  		} else {
  1351  			rr = r
  1352  		}
  1353  		assertInCode(t, fmt.Sprintf("buf = bytes.NewBuffer(stage1[%d])", i), res)
  1354  		assertInCode(t, "dec := json.NewDecoder(buf)", res)
  1355  		assertInCode(t, fmt.Sprintf("dec.Decode(%s)", r), res)
  1356  		assertInCode(t, "P"+strconv.Itoa(i)+",", res)
  1357  		assertInCode(t, fmt.Sprintf("%s = %s", m, rr), res)
  1358  	}
  1359  }
  1360  
  1361  func TestGenerateModel_WithTupleWithExtra(t *testing.T) {
  1362  	specDoc, err := loads.Spec("../fixtures/codegen/todolist.models.yml")
  1363  	require.NoError(t, err)
  1364  
  1365  	definitions := specDoc.Spec().Definitions
  1366  	k := "WithTupleWithExtra"
  1367  	schema := definitions[k]
  1368  	opts := opts()
  1369  	tt := templateTest{t, opts.templates.MustGet("model")}
  1370  	genModel, err := makeGenDefinition(k, "models", schema, specDoc, opts)
  1371  	require.NoError(t, err)
  1372  	require.NotEmpty(t, genModel.ExtraSchemas)
  1373  	require.NotEmpty(t, genModel.Properties)
  1374  
  1375  	assert.False(t, genModel.IsTuple)
  1376  	assert.True(t, genModel.IsComplexObject)
  1377  	assert.False(t, genModel.IsArray)
  1378  	assert.False(t, genModel.IsAnonymous)
  1379  
  1380  	sch := genModel.ExtraSchemas[0]
  1381  	assert.True(t, sch.IsTuple)
  1382  	assert.False(t, sch.IsComplexObject)
  1383  	assert.False(t, sch.IsArray)
  1384  	assert.False(t, sch.IsAnonymous)
  1385  	assert.Equal(t, k+"FlagsTuple0", sch.Name)
  1386  	assert.True(t, sch.HasAdditionalItems)
  1387  	assert.NotEmpty(t, sch.AdditionalItems)
  1388  
  1389  	prop := genModel.Properties[0]
  1390  	assert.False(t, genModel.IsTuple)
  1391  	assert.True(t, genModel.IsComplexObject)
  1392  	assert.False(t, prop.IsArray)
  1393  	assert.False(t, prop.IsAnonymous)
  1394  	assert.Equal(t, k+"FlagsTuple0", prop.GoType)
  1395  	assert.Equal(t, "flags", prop.Name)
  1396  	buf := bytes.NewBuffer(nil)
  1397  	require.NoError(t, tt.template.Execute(buf, genModel))
  1398  
  1399  	ff, err := opts.LanguageOpts.FormatContent("with_tuple.go", buf.Bytes())
  1400  	require.NoError(t, err)
  1401  
  1402  	res := string(ff)
  1403  	assertInCode(t, "swagger:model "+k+"Flags", res)
  1404  	assertInCode(t, "type "+k+"FlagsTuple0 struct {", res)
  1405  	assertInCode(t, "P0 *int64 `json:\"-\"`", res)
  1406  	assertInCode(t, "P1 *string `json:\"-\"`", res)
  1407  	assertInCode(t, k+"FlagsTuple0Items []float32 `json:\"-\"`", res)
  1408  	assertInCode(t, k+"FlagsTuple0) UnmarshalJSON", res)
  1409  	assertInCode(t, k+"FlagsTuple0) MarshalJSON", res)
  1410  	assertInCode(t, "json.Marshal(data)", res)
  1411  
  1412  	for i, p := range sch.Properties {
  1413  		m := "m.P" + strconv.Itoa(i)
  1414  		r := "&dataP" + strconv.Itoa(i)
  1415  		var rr string
  1416  		if !p.IsNullable {
  1417  			rr = "dataP" + strconv.Itoa(i)
  1418  		} else {
  1419  			rr = r
  1420  		}
  1421  		assertInCode(t, fmt.Sprintf("lastIndex = %d", i), res)
  1422  		assertInCode(t, fmt.Sprintf("buf = bytes.NewBuffer(stage1[%d])", i), res)
  1423  		assertInCode(t, "dec := json.NewDecoder(buf)", res)
  1424  		assertInCode(t, fmt.Sprintf("dec.Decode(%s)", r), res)
  1425  		assertInCode(t, "P"+strconv.Itoa(i)+",", res)
  1426  		assertInCode(t, fmt.Sprintf("%s = %s", m, rr), res)
  1427  	}
  1428  
  1429  	assertInCode(t, "var lastIndex int", res)
  1430  	assertInCode(t, "var toadd float32", res)
  1431  	assertInCode(t, "for _, val := range stage1[lastIndex+1:]", res)
  1432  	assertInCode(t, "buf = bytes.NewBuffer(val)", res)
  1433  	assertInCode(t, "dec := json.NewDecoder(buf)", res)
  1434  	assertInCode(t, "dec.Decode(&toadd)", res)
  1435  	assertInCode(t, "json.Marshal(data)", res)
  1436  	assertInCode(t, "for _, v := range m."+k+"FlagsTuple0Items", res)
  1437  }
  1438  
  1439  func TestGenerateModel_WithAllOfAndDiscriminator(t *testing.T) {
  1440  	specDoc, err := loads.Spec("../fixtures/codegen/todolist.models.yml")
  1441  	require.NoError(t, err)
  1442  
  1443  	definitions := specDoc.Spec().Definitions
  1444  	schema := definitions["Cat"]
  1445  	opts := opts()
  1446  	genModel, err := makeGenDefinition("Cat", "models", schema, specDoc, opts)
  1447  	require.NoError(t, err)
  1448  	require.Len(t, genModel.AllOf, 2)
  1449  
  1450  	assert.True(t, genModel.IsComplexObject)
  1451  	assert.Equal(t, "Cat", genModel.Name)
  1452  	assert.Equal(t, "Cat", genModel.GoType)
  1453  	buf := bytes.NewBuffer(nil)
  1454  	require.NoError(t, opts.templates.MustGet("model").Execute(buf, genModel))
  1455  
  1456  	ct, err := opts.LanguageOpts.FormatContent("cat.go", buf.Bytes())
  1457  	require.NoError(t, err)
  1458  
  1459  	res := string(ct)
  1460  	assertInCode(t, "type Cat struct {", res)
  1461  	assertInCode(t, "Pet", res)
  1462  	assertInCode(t, "HuntingSkill *string `json:\"huntingSkill\"`", res)
  1463  }
  1464  
  1465  func TestGenerateModel_WithAllOfAndDiscriminatorAndArrayOfPolymorphs(t *testing.T) {
  1466  	specDoc, err := loads.Spec("../fixtures/codegen/todolist.models.yml")
  1467  	require.NoError(t, err)
  1468  
  1469  	definitions := specDoc.Spec().Definitions
  1470  	schema := definitions["PetWithPets"]
  1471  	opts := opts()
  1472  	genModel, err := makeGenDefinition("PetWithPets", "models", schema, specDoc, opts)
  1473  	require.NoError(t, err)
  1474  	require.Len(t, genModel.AllOf, 2)
  1475  
  1476  	assert.True(t, genModel.IsComplexObject)
  1477  	assert.Equal(t, "PetWithPets", genModel.Name)
  1478  	assert.Equal(t, "PetWithPets", genModel.GoType)
  1479  	buf := bytes.NewBuffer(nil)
  1480  	require.NoError(t, opts.templates.MustGet("model").Execute(buf, genModel))
  1481  
  1482  	ct, err := opts.LanguageOpts.FormatContent("PetWithPets.go", buf.Bytes())
  1483  	require.NoError(t, err)
  1484  
  1485  	res := string(ct)
  1486  	assertInCode(t, "type PetWithPets struct {", res)
  1487  	assertInCode(t, "UnmarshalPetSlice", res)
  1488  }
  1489  
  1490  func TestGenerateModel_WithAllOf(t *testing.T) {
  1491  	specDoc, err := loads.Spec("../fixtures/codegen/todolist.models.yml")
  1492  	require.NoError(t, err)
  1493  
  1494  	definitions := specDoc.Spec().Definitions
  1495  	schema := definitions["WithAllOf"]
  1496  	opts := opts()
  1497  	genModel, err := makeGenDefinition("WithAllOf", "models", schema, specDoc, opts)
  1498  	require.NoError(t, err)
  1499  
  1500  	assert.Len(t, genModel.AllOf, 7)
  1501  	assert.True(t, genModel.AllOf[1].HasAdditionalProperties)
  1502  	assert.True(t, genModel.IsComplexObject)
  1503  	assert.Equal(t, "WithAllOf", genModel.Name)
  1504  	assert.Equal(t, "WithAllOf", genModel.GoType)
  1505  	buf := bytes.NewBuffer(nil)
  1506  	require.NoError(t, opts.templates.MustGet("model").Execute(buf, genModel))
  1507  
  1508  	ct, err := opts.LanguageOpts.FormatContent("all_of_schema.go", buf.Bytes())
  1509  	require.NoError(t, err)
  1510  
  1511  	res := string(ct)
  1512  	assertInCode(t, "type WithAllOf struct {", res)
  1513  	assertInCode(t, "type WithAllOfAO2P2 struct {", res)
  1514  	assertInCode(t, "type WithAllOfAO3P3 struct {", res)
  1515  	assertInCode(t, "type WithAllOfParamsAnon struct {", res)
  1516  	assertInCode(t, "type WithAllOfAO4Tuple4 struct {", res)
  1517  	assertInCode(t, "type WithAllOfAO5Tuple5 struct {", res)
  1518  	assertInCode(t, "Notable", res)
  1519  	assertInCode(t, "Title string `json:\"title,omitempty\"`", res)
  1520  	assertInCode(t, "Body string `json:\"body,omitempty\"`", res)
  1521  	assertInCode(t, "Name string `json:\"name,omitempty\"`", res)
  1522  	assertInCode(t, "P0 *float32 `json:\"-\"`", res)
  1523  	assertInCode(t, "P0 *float64 `json:\"-\"`", res)
  1524  	assertInCode(t, "P1 *strfmt.DateTime `json:\"-\"`", res)
  1525  	assertInCode(t, "P1 *strfmt.Date `json:\"-\"`", res)
  1526  	assertInCode(t, "Opinion string `json:\"opinion,omitempty\"`", res)
  1527  	assertInCode(t, "WithAllOfAO5Tuple5Items []strfmt.Password `json:\"-\"`", res)
  1528  	assertInCode(t, "AO1 map[string]int32 `json:\"-\"`", res)
  1529  	assertInCode(t, "WithAllOfAO2P2 map[string]int64 `json:\"-\"`", res)
  1530  }
  1531  
  1532  func findProperty(properties []GenSchema, name string) *GenSchema {
  1533  	for _, p := range properties {
  1534  		if p.Name == name {
  1535  			return &p
  1536  		}
  1537  	}
  1538  	return nil
  1539  }
  1540  
  1541  func getDefinitionProperty(genModel *GenDefinition, name string) *GenSchema {
  1542  	return findProperty(genModel.Properties, name)
  1543  }
  1544  
  1545  func TestNumericKeys(t *testing.T) {
  1546  	specDoc, err := loads.Spec("../fixtures/bugs/162/swagger.yml")
  1547  	require.NoError(t, err)
  1548  
  1549  	definitions := specDoc.Spec().Definitions
  1550  	schema := definitions["AvatarUrls"]
  1551  	opts := opts()
  1552  	genModel, err := makeGenDefinition("AvatarUrls", "models", schema, specDoc, opts)
  1553  	require.NoError(t, err)
  1554  
  1555  	buf := bytes.NewBuffer(nil)
  1556  	require.NoError(t, opts.templates.MustGet("model").Execute(buf, genModel))
  1557  
  1558  	ct, err := opts.LanguageOpts.FormatContent("all_of_schema.go", buf.Bytes())
  1559  	require.NoError(t, err)
  1560  
  1561  	res := string(ct)
  1562  	assertInCode(t, "Nr16x16 string `json:\"16x16,omitempty\"`", res)
  1563  }
  1564  
  1565  func TestGenModel_Issue196(t *testing.T) {
  1566  	specDoc, err := loads.Spec("../fixtures/bugs/196/swagger.yml")
  1567  	require.NoError(t, err)
  1568  
  1569  	definitions := specDoc.Spec().Definitions
  1570  	schema := definitions["Event"]
  1571  	opts := opts()
  1572  	genModel, err := makeGenDefinition("Event", "models", schema, specDoc, opts)
  1573  	require.NoError(t, err)
  1574  
  1575  	buf := bytes.NewBuffer(nil)
  1576  	require.NoError(t, opts.templates.MustGet("model").Execute(buf, genModel))
  1577  
  1578  	ct, err := opts.LanguageOpts.FormatContent("primitive_event.go", buf.Bytes())
  1579  	require.NoError(t, err)
  1580  
  1581  	res := string(ct)
  1582  	assertInCode(t, "Event) Validate(formats strfmt.Registry) error", res)
  1583  }
  1584  
  1585  func TestGenModel_Issue222(t *testing.T) {
  1586  	specDoc, err := loads.Spec("../fixtures/codegen/tasklist.basic.yml")
  1587  	require.NoError(t, err)
  1588  
  1589  	definitions := specDoc.Spec().Definitions
  1590  	k := "Price"
  1591  	opts := opts()
  1592  	genModel, err := makeGenDefinition(k, "models", definitions[k], specDoc, opts)
  1593  	require.NoError(t, err)
  1594  	require.True(t, genModel.HasValidations)
  1595  
  1596  	buf := bytes.NewBuffer(nil)
  1597  	require.NoError(t, opts.templates.MustGet("model").Execute(buf, genModel))
  1598  
  1599  	ct, err := opts.LanguageOpts.FormatContent("price.go", buf.Bytes())
  1600  	require.NoError(t, err)
  1601  
  1602  	res := string(ct)
  1603  	assertInCode(t, "Price) Validate(formats strfmt.Registry) error", res)
  1604  	assertInCode(t, "Currency Currency `json:\"currency,omitempty\"`", res)
  1605  	assertInCode(t, "m.Currency.Validate(formats); err != nil", res)
  1606  }
  1607  
  1608  func TestGenModel_Issue243(t *testing.T) {
  1609  	specDoc, err := loads.Spec("../fixtures/codegen/todolist.models.yml")
  1610  	require.NoError(t, err)
  1611  
  1612  	definitions := specDoc.Spec().Definitions
  1613  	k := "HasDynMeta"
  1614  	opts := opts()
  1615  	genModel, err := makeGenDefinition(k, "models", definitions[k], specDoc, opts)
  1616  	require.NoError(t, err)
  1617  
  1618  	buf := bytes.NewBuffer(nil)
  1619  	require.NoError(t, opts.templates.MustGet("model").Execute(buf, genModel))
  1620  
  1621  	ct, err := opts.LanguageOpts.FormatContent("has_dyn_meta.go", buf.Bytes())
  1622  	require.NoError(t, err)
  1623  
  1624  	res := string(ct)
  1625  	assertInCode(t, "Metadata DynamicMetaData `json:\"metadata,omitempty\"`", res)
  1626  }
  1627  
  1628  func TestGenModel_Issue252(t *testing.T) {
  1629  	specDoc, err := loads.Spec("../fixtures/bugs/252/swagger.json")
  1630  	require.NoError(t, err)
  1631  
  1632  	definitions := specDoc.Spec().Definitions
  1633  	k := "SodaBrand"
  1634  	opts := opts()
  1635  	genModel, err := makeGenDefinition(k, "models", definitions[k], specDoc, opts)
  1636  	require.NoError(t, err)
  1637  	require.False(t, genModel.IsNullable)
  1638  
  1639  	buf := bytes.NewBuffer(nil)
  1640  	require.NoError(t, opts.templates.MustGet("model").Execute(buf, genModel))
  1641  
  1642  	ct, err := opts.LanguageOpts.FormatContent("soda_brand.go", buf.Bytes())
  1643  	require.NoError(t, err)
  1644  
  1645  	res := string(ct)
  1646  	assertInCode(t, "type "+k+" string", res)
  1647  	assertInCode(t, "(m "+k+") validateSodaBrand", res)
  1648  	assertInCode(t, "(m "+k+") Validate", res)
  1649  }
  1650  
  1651  func TestGenModel_Issue251(t *testing.T) {
  1652  	specDoc, err := loads.Spec("../fixtures/bugs/251/swagger.yml")
  1653  	require.NoError(t, err)
  1654  
  1655  	definitions := specDoc.Spec().Definitions
  1656  	k := "example"
  1657  	opts := opts()
  1658  	genModel, err := makeGenDefinition(k, "models", definitions[k], specDoc, opts)
  1659  	require.NoError(t, err)
  1660  
  1661  	buf := bytes.NewBuffer(nil)
  1662  	require.NoError(t, opts.templates.MustGet("model").Execute(buf, genModel))
  1663  
  1664  	ct, err := opts.LanguageOpts.FormatContent("example.go", buf.Bytes())
  1665  	require.NoError(t, err)
  1666  
  1667  	res := string(ct)
  1668  
  1669  	assertInCode(t, "type "+swag.ToGoName(k)+" struct", res)
  1670  	assertInCode(t, "Begin *strfmt.DateTime `json:\"begin\"`", res)
  1671  	assertInCode(t, "End strfmt.DateTime `json:\"end,omitempty\"`", res)
  1672  	assertInCode(t, "Name string `json:\"name,omitempty\"`", res)
  1673  	assertInCode(t, "(m *"+swag.ToGoName(k)+") validateBegin", res)
  1674  	assertInCode(t, "(m *"+swag.ToGoName(k)+") Validate", res)
  1675  }
  1676  
  1677  func TestGenModel_Issue257(t *testing.T) {
  1678  	specDoc, err := loads.Spec("../fixtures/codegen/todolist.models.yml")
  1679  	require.NoError(t, err)
  1680  
  1681  	definitions := specDoc.Spec().Definitions
  1682  	k := "HasSpecialCharProp"
  1683  	opts := opts()
  1684  	genModel, err := makeGenDefinition(k, "models", definitions[k], specDoc, opts)
  1685  	require.NoError(t, err)
  1686  
  1687  	buf := bytes.NewBuffer(nil)
  1688  	require.NoError(t, opts.templates.MustGet("model").Execute(buf, genModel))
  1689  
  1690  	ct, err := opts.LanguageOpts.FormatContent("example.go", buf.Bytes())
  1691  	require.NoError(t, err)
  1692  
  1693  	res := string(ct)
  1694  
  1695  	assertInCode(t, "type "+swag.ToGoName(k)+" struct", res)
  1696  	assertInCode(t, "AtType string `json:\"@type,omitempty\"`", res)
  1697  	assertInCode(t, "Type string `json:\"type,omitempty\"`", res)
  1698  }
  1699  
  1700  func TestGenModel_Issue340(t *testing.T) {
  1701  	specDoc, err := loads.Spec("../fixtures/codegen/todolist.models.yml")
  1702  	require.NoError(t, err)
  1703  
  1704  	definitions := specDoc.Spec().Definitions
  1705  	k := "ImageTar"
  1706  	opts := opts()
  1707  	genModel, err := makeGenDefinition(k, "models", definitions[k], specDoc, opts)
  1708  	require.NoError(t, err)
  1709  
  1710  	buf := bytes.NewBuffer(nil)
  1711  	require.NoError(t, opts.templates.MustGet("model").Execute(buf, genModel))
  1712  
  1713  	ct, err := opts.LanguageOpts.FormatContent("image_tar.go", buf.Bytes())
  1714  	require.NoError(t, err)
  1715  
  1716  	res := string(ct)
  1717  
  1718  	assertInCode(t, "type "+swag.ToGoName(k)+" io.ReadCloser", res)
  1719  	assertNotInCode(t, "func (m ImageTar) Validate(formats strfmt.Registry) error", res)
  1720  }
  1721  
  1722  func TestGenModel_Issue381(t *testing.T) {
  1723  	specDoc, err := loads.Spec("../fixtures/codegen/todolist.models.yml")
  1724  	require.NoError(t, err)
  1725  
  1726  	definitions := specDoc.Spec().Definitions
  1727  	k := "flags_list"
  1728  	opts := opts()
  1729  	genModel, err := makeGenDefinition(k, "models", definitions[k], specDoc, opts)
  1730  	require.NoError(t, err)
  1731  
  1732  	buf := bytes.NewBuffer(nil)
  1733  	require.NoError(t, opts.templates.MustGet("model").Execute(buf, genModel))
  1734  
  1735  	ct, err := opts.LanguageOpts.FormatContent("flags_list.go", buf.Bytes())
  1736  	require.NoError(t, err)
  1737  
  1738  	res := string(ct)
  1739  	assertNotInCode(t, "m[i] != nil", res)
  1740  }
  1741  
  1742  func TestGenModel_Issue300(t *testing.T) {
  1743  	specDoc, err := loads.Spec("../fixtures/codegen/todolist.models.yml")
  1744  	require.NoError(t, err)
  1745  
  1746  	definitions := specDoc.Spec().Definitions
  1747  	k := "ActionItem"
  1748  	opts := opts()
  1749  	genModel, err := makeGenDefinition(k, "models", definitions[k], specDoc, opts)
  1750  	require.NoError(t, err)
  1751  
  1752  	buf := bytes.NewBuffer(nil)
  1753  	require.NoError(t, opts.templates.MustGet("model").Execute(buf, genModel))
  1754  
  1755  	ct, err := opts.LanguageOpts.FormatContent("action_item.go", buf.Bytes())
  1756  	require.NoError(t, err)
  1757  
  1758  	res := string(ct)
  1759  	assertInCode(t, "Name ActionName `json:\"name\"`", res)
  1760  }
  1761  
  1762  func TestGenModel_Issue398(t *testing.T) {
  1763  	specDoc, err := loads.Spec("../fixtures/codegen/todolist.models.yml")
  1764  	require.NoError(t, err)
  1765  
  1766  	definitions := specDoc.Spec().Definitions
  1767  	k := "Property"
  1768  	opts := opts()
  1769  	genModel, err := makeGenDefinition(k, "models", definitions[k], specDoc, opts)
  1770  	require.NoError(t, err)
  1771  
  1772  	buf := bytes.NewBuffer(nil)
  1773  	require.NoError(t, opts.templates.MustGet("model").Execute(buf, genModel))
  1774  
  1775  	ct, err := opts.LanguageOpts.FormatContent("action_item.go", buf.Bytes())
  1776  	require.NoError(t, err)
  1777  
  1778  	res := string(ct)
  1779  	assertInCode(t, "Computed bool `json:\"computed,omitempty\"`", res)
  1780  	assertInCode(t, "Intval *int64 `json:\"intval\"`", res)
  1781  	assertInCode(t, "PropType *string `json:\"propType\"`", res)
  1782  	assertInCode(t, "Strval *string `json:\"strval\"`", res)
  1783  }
  1784  
  1785  func TestGenModel_Issue454(t *testing.T) {
  1786  	specDoc, err := loads.Spec("../fixtures/bugs/454/swagger.yml")
  1787  	require.NoError(t, err)
  1788  
  1789  	definitions := specDoc.Spec().Definitions
  1790  	schema := definitions["genericResource"]
  1791  	opts := opts()
  1792  	genModel, err := makeGenDefinition("genericResource", "models", schema, specDoc, opts)
  1793  	require.NoError(t, err)
  1794  
  1795  	buf := bytes.NewBuffer(nil)
  1796  	require.NoError(t, opts.templates.MustGet("model").Execute(buf, genModel))
  1797  
  1798  	ct, err := opts.LanguageOpts.FormatContent("generic_resource.go", buf.Bytes())
  1799  	require.NoError(t, err)
  1800  
  1801  	res := string(ct)
  1802  	assertInCode(t, "rcv.Meta = stage1.Meta", res)
  1803  	assertInCode(t, "json.Marshal(stage1)", res)
  1804  	assertInCode(t, "stage1.Meta = m.Meta", res)
  1805  	assertInCode(t, "json.Marshal(m.GenericResource)", res)
  1806  }
  1807  
  1808  func TestGenModel_Issue423(t *testing.T) {
  1809  	specDoc, err := loads.Spec("../fixtures/bugs/423/swagger.json")
  1810  	require.NoError(t, err)
  1811  
  1812  	definitions := specDoc.Spec().Definitions
  1813  	schema := definitions["SRN"]
  1814  	opts := opts()
  1815  	genModel, err := makeGenDefinition("SRN", "models", schema, specDoc, opts)
  1816  	require.NoError(t, err)
  1817  
  1818  	buf := bytes.NewBuffer(nil)
  1819  	require.NoError(t, opts.templates.MustGet("model").Execute(buf, genModel))
  1820  
  1821  	ct, err := opts.LanguageOpts.FormatContent("SRN.go", buf.Bytes())
  1822  	require.NoError(t, err)
  1823  
  1824  	res := string(ct)
  1825  	assertInCode(t, "propSite, err := UnmarshalSite(bytes.NewBuffer(data.Site), runtime.JSONConsumer())", res)
  1826  	assertInCode(t, "result.siteField = propSite", res)
  1827  }
  1828  
  1829  func TestGenModel_Issue453(t *testing.T) {
  1830  	specDoc, err := loads.Spec("../fixtures/bugs/453/swagger.yml")
  1831  	require.NoError(t, err)
  1832  
  1833  	definitions := specDoc.Spec().Definitions
  1834  	k := "out_obj"
  1835  	opts := opts()
  1836  	genModel, err := makeGenDefinition(k, "models", definitions[k], specDoc, opts)
  1837  	require.NoError(t, err)
  1838  
  1839  	buf := bytes.NewBuffer(nil)
  1840  	require.NoError(t, opts.templates.MustGet("model").Execute(buf, genModel))
  1841  
  1842  	ct, err := opts.LanguageOpts.FormatContent("out_obj.go", buf.Bytes())
  1843  	require.NoError(t, err)
  1844  
  1845  	res := string(ct)
  1846  	assertInCode(t, `func (m *OutObj) validateFld3(formats strfmt.Registry)`, res)
  1847  }
  1848  
  1849  func TestGenModel_Issue455(t *testing.T) {
  1850  	specDoc, err := loads.Spec("../fixtures/bugs/455/swagger.yml")
  1851  	require.NoError(t, err)
  1852  
  1853  	definitions := specDoc.Spec().Definitions
  1854  	k := "out_obj"
  1855  	opts := opts()
  1856  	genModel, err := makeGenDefinition(k, "models", definitions[k], specDoc, opts)
  1857  	require.NoError(t, err)
  1858  
  1859  	buf := bytes.NewBuffer(nil)
  1860  	require.NoError(t, opts.templates.MustGet("model").Execute(buf, genModel))
  1861  
  1862  	ct, err := opts.LanguageOpts.FormatContent("out_obj.go", buf.Bytes())
  1863  	require.NoError(t, err)
  1864  
  1865  	res := string(ct)
  1866  	assertInCode(t, `if err := validate.Required("fld2", "body", m.Fld2); err != nil {`, res)
  1867  }
  1868  
  1869  func TestGenModel_Issue763(t *testing.T) {
  1870  	specDoc, err := loads.Spec("../fixtures/bugs/763/swagger.yml")
  1871  	require.NoError(t, err)
  1872  
  1873  	definitions := specDoc.Spec().Definitions
  1874  	k := "test_list"
  1875  	opts := opts()
  1876  	genModel, err := makeGenDefinition(k, "models", definitions[k], specDoc, opts)
  1877  	require.NoError(t, err)
  1878  
  1879  	buf := bytes.NewBuffer(nil)
  1880  	require.NoError(t, opts.templates.MustGet("model").Execute(buf, genModel))
  1881  
  1882  	ct, err := opts.LanguageOpts.FormatContent("test_list.go", buf.Bytes())
  1883  	require.NoError(t, err)
  1884  
  1885  	res := string(ct)
  1886  	assertInCode(t, "TheArray []*int32 `json:\"the_array\"`", res)
  1887  	assertInCode(t, `validate.MinimumInt("the_array"+"."+strconv.Itoa(i), "body", int64(*m.TheArray[i]), 0, false)`, res)
  1888  	assertInCode(t, `validate.MaximumInt("the_array"+"."+strconv.Itoa(i), "body", int64(*m.TheArray[i]), 10, false)`, res)
  1889  }
  1890  
  1891  func TestGenModel_Issue811_NullType(t *testing.T) {
  1892  	specDoc, err := loads.Spec("../fixtures/bugs/811/swagger.json")
  1893  	require.NoError(t, err)
  1894  
  1895  	definitions := specDoc.Spec().Definitions
  1896  	k := "teamRepos"
  1897  	opts := opts()
  1898  	genModel, err := makeGenDefinition(k, "models", definitions[k], specDoc, opts)
  1899  	require.NoError(t, err)
  1900  
  1901  	buf := bytes.NewBuffer(nil)
  1902  	require.NoError(t, opts.templates.MustGet("model").Execute(buf, genModel))
  1903  
  1904  	ct, err := opts.LanguageOpts.FormatContent("team_repos.go", buf.Bytes())
  1905  	require.NoError(t, err)
  1906  
  1907  	res := string(ct)
  1908  	assertInCode(t, "Language interface{} `json:\"language,omitempty\"`", res)
  1909  }
  1910  
  1911  func TestGenModel_Issue811_Emojis(t *testing.T) {
  1912  	specDoc, err := loads.Spec("../fixtures/bugs/811/swagger.json")
  1913  	require.NoError(t, err)
  1914  
  1915  	definitions := specDoc.Spec().Definitions
  1916  	k := "emojis"
  1917  	opts := opts()
  1918  	genModel, err := makeGenDefinition(k, "models", definitions[k], specDoc, opts)
  1919  	require.NoError(t, err)
  1920  
  1921  	buf := bytes.NewBuffer(nil)
  1922  	require.NoError(t, opts.templates.MustGet("model").Execute(buf, genModel))
  1923  
  1924  	ct, err := opts.LanguageOpts.FormatContent("team_repos.go", buf.Bytes())
  1925  	require.NoError(t, err)
  1926  
  1927  	res := string(ct)
  1928  	assertInCode(t, "Plus1 string `json:\"+1,omitempty\"`", res)
  1929  	assertInCode(t, "Minus1 string `json:\"-1,omitempty\"`", res)
  1930  }
  1931  
  1932  func TestGenModel_Issue752_EOFErr(t *testing.T) {
  1933  	specDoc, err := loads.Spec("../fixtures/codegen/azure-text-analyis.json")
  1934  	require.NoError(t, err)
  1935  
  1936  	definitions := specDoc.Spec().Definitions
  1937  	k := "OperationResult"
  1938  	opts := opts()
  1939  	genModel, err := makeGenDefinition(k, "models", definitions[k], specDoc, opts)
  1940  	require.NoError(t, err)
  1941  
  1942  	buf := bytes.NewBuffer(nil)
  1943  	require.NoError(t, opts.templates.MustGet("model").Execute(buf, genModel))
  1944  
  1945  	ct, err := opts.LanguageOpts.FormatContent("out_obj.go", buf.Bytes())
  1946  	require.NoError(t, err)
  1947  
  1948  	res := string(ct)
  1949  	assertInCode(t, `&& err != io.EOF`, res)
  1950  }
  1951  
  1952  func TestImports_ExistingModel(t *testing.T) {
  1953  	specDoc, err := loads.Spec("../fixtures/codegen/existing-model.yml")
  1954  	require.NoError(t, err)
  1955  
  1956  	definitions := specDoc.Spec().Definitions
  1957  	opts := opts()
  1958  
  1959  	k := "JsonWebKeySet"
  1960  	genModel, err := makeGenDefinition(k, "models", definitions[k], specDoc, opts)
  1961  	require.NoError(t, err)
  1962  
  1963  	require.NotNil(t, genModel)
  1964  	require.NotNil(t, genModel.Imports)
  1965  	assert.Equal(t, "github.com/user/package", genModel.Imports["jwk"])
  1966  
  1967  	k = "JsonWebKey"
  1968  	genModel, err = makeGenDefinition(k, "models", definitions[k], specDoc, opts)
  1969  	require.NoError(t, err)
  1970  
  1971  	require.NotNil(t, genModel)
  1972  	require.NotNil(t, genModel.Imports)
  1973  	assert.Equal(t, "github.com/user/package", genModel.Imports["jwk"])
  1974  }
  1975  
  1976  func TestGenModel_Issue786(t *testing.T) {
  1977  	specDoc, err := loads.Spec("../fixtures/bugs/786/swagger.yml")
  1978  	require.NoError(t, err)
  1979  
  1980  	definitions := specDoc.Spec().Definitions
  1981  	k := "MyFirstObject"
  1982  	opts := opts()
  1983  	genModel, err := makeGenDefinition(k, "models", definitions[k], specDoc, opts)
  1984  	require.NoError(t, err)
  1985  
  1986  	require.False(t, genModel.Properties[0].AdditionalProperties.IsNullable)
  1987  
  1988  	buf := bytes.NewBuffer(nil)
  1989  	require.NoError(t, opts.templates.MustGet("model").Execute(buf, genModel))
  1990  
  1991  	ct, err := opts.LanguageOpts.FormatContent("MyFirstObject.go", buf.Bytes())
  1992  	require.NoError(t, err)
  1993  
  1994  	res := string(ct)
  1995  	assertInCode(t, `m.validateEntreeChoiceValueEnum("entree_choice"+"."+k, "body", m.EntreeChoice[k])`, res)
  1996  }
  1997  
  1998  func TestGenModel_Issue822(t *testing.T) {
  1999  	specDoc, err := loads.Spec("../fixtures/bugs/822/swagger.yml")
  2000  	require.NoError(t, err)
  2001  
  2002  	definitions := specDoc.Spec().Definitions
  2003  	k := "Pet"
  2004  	opts := opts()
  2005  	genModel, err := makeGenDefinition(k, "models", definitions[k], specDoc, opts)
  2006  	require.NoError(t, err)
  2007  
  2008  	ap := genModel.AdditionalProperties
  2009  	require.True(t, genModel.HasAdditionalProperties)
  2010  	require.NotNil(t, ap)
  2011  	require.False(t, ap.IsNullable)
  2012  
  2013  	buf := bytes.NewBuffer(nil)
  2014  	require.NoError(t, opts.templates.MustGet("model").Execute(buf, genModel))
  2015  
  2016  	ct, err := opts.LanguageOpts.FormatContent("pet.go", buf.Bytes())
  2017  	require.NoError(t, err)
  2018  
  2019  	res := string(ct)
  2020  	assertInCode(t, `PetAdditionalProperties map[string]interface{}`, res)
  2021  	assertInCode(t, `m.PetAdditionalProperties = result`, res)
  2022  	assertInCode(t, `additional, err := json.Marshal(m.PetAdditionalProperties)`, res)
  2023  }
  2024  
  2025  func TestGenModel_Issue981(t *testing.T) {
  2026  	specDoc, err := loads.Spec("../fixtures/bugs/981/swagger.json")
  2027  	require.NoError(t, err)
  2028  
  2029  	definitions := specDoc.Spec().Definitions
  2030  	k := "User"
  2031  	opts := opts()
  2032  	genModel, err := makeGenDefinition(k, "models", definitions[k], specDoc, opts)
  2033  	require.NoError(t, err)
  2034  
  2035  	buf := bytes.NewBuffer(nil)
  2036  	require.NoError(t, opts.templates.MustGet("model").Execute(buf, genModel))
  2037  
  2038  	ct, err := opts.LanguageOpts.FormatContent("user.go", buf.Bytes())
  2039  	require.NoError(t, err)
  2040  
  2041  	res := string(ct)
  2042  	assertInCode(t, "FirstName string `json:\"first_name,omitempty\"`", res)
  2043  	assertInCode(t, "LastName string `json:\"last_name,omitempty\"`", res)
  2044  	assertInCode(t, "if swag.IsZero(m.Type)", res)
  2045  	assertInCode(t, `validate.MinimumInt("user_type", "body", m.Type, 1, false)`, res)
  2046  	assertInCode(t, `validate.MaximumInt("user_type", "body", m.Type, 5, false)`, res)
  2047  }
  2048  
  2049  func TestGenModel_Issue1341(t *testing.T) {
  2050  	specDoc, err := loads.Spec("../fixtures/bugs/1341/swagger.yaml")
  2051  	require.NoError(t, err)
  2052  
  2053  	definitions := specDoc.Spec().Definitions
  2054  	k := "ExecutableValueString"
  2055  	schema := definitions[k]
  2056  	opts := opts()
  2057  	genModel, err := makeGenDefinition(k, "models", schema, specDoc, opts)
  2058  	require.NoError(t, err)
  2059  
  2060  	buf := bytes.NewBuffer(nil)
  2061  	require.NoError(t, opts.templates.MustGet("model").Execute(buf, genModel))
  2062  
  2063  	ff, err := opts.LanguageOpts.FormatContent("executable_value_string.go", buf.Bytes())
  2064  	require.NoError(t, err)
  2065  
  2066  	res := string(ff)
  2067  	assertInCode(t, `return errors.New(422, "invalid ValueType value: %q", base.ValueType`, res)
  2068  	assertInCode(t, "result.testField = base.Test", res)
  2069  	assertInCode(t, "Test *string `json:\"Test\"`", res)
  2070  	assertInCode(t, "Test: m.Test(),", res)
  2071  }
  2072  
  2073  // This tests to check that format validation is performed on non required schema properties
  2074  func TestGenModel_Issue1347(t *testing.T) {
  2075  	specDoc, err := loads.Spec("../fixtures/bugs/1347/fixture-1347.yaml")
  2076  	require.NoError(t, err)
  2077  
  2078  	definitions := specDoc.Spec().Definitions
  2079  	schema := definitions["ContainerConfig"]
  2080  	opts := opts()
  2081  	genModel, err := makeGenDefinition("ContainerConfig", "models", schema, specDoc, opts)
  2082  	require.NoError(t, err)
  2083  
  2084  	buf := bytes.NewBuffer(nil)
  2085  	require.NoError(t, opts.templates.MustGet("model").Execute(buf, genModel))
  2086  
  2087  	ff, err := opts.LanguageOpts.FormatContent("Foo.go", buf.Bytes())
  2088  	require.NoError(t, err)
  2089  
  2090  	res := string(ff)
  2091  	// Just verify that the validation call is generated even though we add a non-required property
  2092  	assertInCode(t, `validate.FormatOf("config1", "body", "hostname", m.Config1.String(), formats)`, res)
  2093  }
  2094  
  2095  // This tests to check that format validation is performed on MAC format
  2096  func TestGenModel_Issue1348(t *testing.T) {
  2097  	specDoc, err := loads.Spec("../fixtures/bugs/1348/fixture-1348.yaml")
  2098  	require.NoError(t, err)
  2099  
  2100  	definitions := specDoc.Spec().Definitions
  2101  	k := "ContainerConfig"
  2102  	schema := definitions[k]
  2103  	opts := opts()
  2104  	genModel, err := makeGenDefinition(k, "models", schema, specDoc, opts)
  2105  	require.NoError(t, err)
  2106  
  2107  	buf := bytes.NewBuffer(nil)
  2108  	require.NoError(t, opts.templates.MustGet("model").Execute(buf, genModel))
  2109  
  2110  	ct, err := opts.LanguageOpts.FormatContent("foo.go", buf.Bytes())
  2111  	require.NoError(t, err)
  2112  
  2113  	res := string(ct)
  2114  	// Just verify that the validation call is generated with proper format
  2115  	assertInCode(t, `if err := validate.FormatOf("config1", "body", "mac", m.Config1.String(), formats)`, res)
  2116  }
  2117  
  2118  // This tests that additionalProperties with validation is generated properly.
  2119  func TestGenModel_Issue1198(t *testing.T) {
  2120  	specDoc, err := loads.Spec("../fixtures/bugs/1198/fixture-1198.yaml")
  2121  	require.NoError(t, err)
  2122  
  2123  	definitions := specDoc.Spec().Definitions
  2124  	k := "pet"
  2125  	schema := definitions[k]
  2126  	opts := opts()
  2127  	genModel, err := makeGenDefinition(k, "models", schema, specDoc, opts)
  2128  	require.NoError(t, err)
  2129  
  2130  	buf := bytes.NewBuffer(nil)
  2131  	require.NoError(t, opts.templates.MustGet("model").Execute(buf, genModel))
  2132  
  2133  	ct, err := opts.LanguageOpts.FormatContent("foo.go", buf.Bytes())
  2134  	require.NoError(t, err)
  2135  
  2136  	res := string(ct)
  2137  	// Just verify that the validation call is generated with proper format
  2138  	assertInCode(t, `if err := m.validateDate(formats); err != nil {`, res)
  2139  }
  2140  
  2141  // This tests that additionalProperties with validation is generated properly.
  2142  func TestGenModel_Issue1397a(t *testing.T) {
  2143  	specDoc, err := loads.Spec("../fixtures/bugs/1397/fixture-1397a.yaml")
  2144  	require.NoError(t, err)
  2145  
  2146  	definitions := specDoc.Spec().Definitions
  2147  	k := "ContainerConfig"
  2148  	schema := definitions[k]
  2149  	opts := opts()
  2150  	genModel, err := makeGenDefinition(k, "models", schema, specDoc, opts)
  2151  	require.NoError(t, err)
  2152  
  2153  	buf := bytes.NewBuffer(nil)
  2154  	require.NoError(t, opts.templates.MustGet("model").Execute(buf, genModel))
  2155  
  2156  	ct, err := opts.LanguageOpts.FormatContent("foo.go", buf.Bytes())
  2157  	require.NoError(t, err)
  2158  
  2159  	res := string(ct)
  2160  	// Just verify that the validation call is generated with proper format
  2161  	assertInCode(t, `if swag.IsZero(m[k]) { // not required`, res)
  2162  }
  2163  
  2164  // This tests that an enum of object values validates properly.
  2165  func TestGenModel_Issue1397b(t *testing.T) {
  2166  	specDoc, err := loads.Spec("../fixtures/bugs/1397/fixture-1397b.yaml")
  2167  	require.NoError(t, err)
  2168  
  2169  	definitions := specDoc.Spec().Definitions
  2170  	k := "ContainerConfig"
  2171  	schema := definitions[k]
  2172  	opts := opts()
  2173  	genModel, err := makeGenDefinition(k, "models", schema, specDoc, opts)
  2174  	require.NoError(t, err)
  2175  
  2176  	buf := bytes.NewBuffer(nil)
  2177  	require.NoError(t, opts.templates.MustGet("model").Execute(buf, genModel))
  2178  
  2179  	ct, err := opts.LanguageOpts.FormatContent("foo.go", buf.Bytes())
  2180  	require.NoError(t, err)
  2181  
  2182  	res := string(ct)
  2183  	// Just verify that the validation call is generated with proper format
  2184  	assertInCode(t, `if err := m.validateContainerConfigEnum("", "body", m); err != nil {`, res)
  2185  }
  2186  
  2187  // This tests that additionalProperties with an array of polymorphic objects is generated properly.
  2188  func TestGenModel_Issue1409(t *testing.T) {
  2189  	specDoc, err := loads.Spec("../fixtures/bugs/1409/fixture-1409.yaml")
  2190  	require.NoError(t, err)
  2191  
  2192  	definitions := specDoc.Spec().Definitions
  2193  	k := "Graph"
  2194  	schema := definitions[k]
  2195  	opts := opts()
  2196  	genModel, err := makeGenDefinition(k, "models", schema, specDoc, opts)
  2197  	require.NoError(t, err)
  2198  
  2199  	buf := bytes.NewBuffer(nil)
  2200  	require.NoError(t, opts.templates.MustGet("model").Execute(buf, genModel))
  2201  
  2202  	ct, err := opts.LanguageOpts.FormatContent("foo.go", buf.Bytes())
  2203  	require.NoError(t, err)
  2204  
  2205  	res := string(ct)
  2206  	// Just verify that the validation call is generated with proper format
  2207  	assertInCode(t, `nodes, err := UnmarshalNodeSlice(bytes.NewBuffer(data.Nodes), runtime.JSONConsumer())`, res)
  2208  	assertInCode(t, `if err := json.Unmarshal(raw, &rawProps); err != nil {`, res)
  2209  	assertInCode(t, `m.GraphAdditionalProperties[k] = toadd`, res)
  2210  	assertInCode(t, `b3, err = json.Marshal(m.GraphAdditionalProperties)`, res)
  2211  }
  2212  
  2213  // This tests that a model with a discriminator doesn't validation if the field is zero.
  2214  func TestGenModel_Issue2911(t *testing.T) {
  2215  	specDoc, err := loads.Spec("../fixtures/bugs/2911/fixture-2911.yaml")
  2216  	require.NoError(t, err)
  2217  
  2218  	definitions := specDoc.Spec().Definitions
  2219  	k := "animal"
  2220  	schema := definitions[k]
  2221  	opts := opts()
  2222  	genModel, err := makeGenDefinition(k, "models", schema, specDoc, opts)
  2223  	require.NoError(t, err)
  2224  
  2225  	buf := bytes.NewBuffer(nil)
  2226  	require.NoError(t, opts.templates.MustGet("model").Execute(buf, genModel))
  2227  
  2228  	ct, err := opts.LanguageOpts.FormatContent("foo.go", buf.Bytes())
  2229  	require.NoError(t, err)
  2230  
  2231  	res := string(ct)
  2232  
  2233  	// Just verify that the validation call is generated with proper format
  2234  	assertInCode(t, `func (m *Animal) contextValidateKind(ctx context.Context, formats strfmt.Registry) error {
  2235  
  2236  	if swag.IsZero(m.Kind()) { // not required
  2237  		return nil
  2238  	}`, res)
  2239  }
  2240  
  2241  // This tests makes sure model definitions from inline schema in response are properly flattened and get validation
  2242  func TestGenModel_Issue866(t *testing.T) {
  2243  	defer discardOutput()()
  2244  
  2245  	specDoc, err := loads.Spec("../fixtures/bugs/866/fixture-866.yaml")
  2246  	require.NoError(t, err)
  2247  
  2248  	p, ok := specDoc.Spec().Paths.Paths["/"]
  2249  	require.True(t, ok)
  2250  
  2251  	op := p.Get
  2252  	responses := op.Responses.StatusCodeResponses
  2253  	for k, r := range responses {
  2254  		t.Logf("Response: %d", k)
  2255  		schema := *r.Schema
  2256  		opts := opts()
  2257  		genModel, err := makeGenDefinition("GetOKBody", "models", schema, specDoc, opts)
  2258  		require.NoError(t, err)
  2259  
  2260  		buf := bytes.NewBuffer(nil)
  2261  		require.NoError(t, opts.templates.MustGet("model").Execute(buf, genModel))
  2262  
  2263  		ct, err := opts.LanguageOpts.FormatContent("foo.go", buf.Bytes())
  2264  		require.NoError(t, err)
  2265  
  2266  		res := string(ct)
  2267  		assertInCode(t, `if err := validate.Required(`, res)
  2268  		assertInCode(t, `if err := validate.MaxLength(`, res)
  2269  		assertInCode(t, `if err := m.validateAccessToken(formats); err != nil {`, res)
  2270  		assertInCode(t, `if err := m.validateAccountID(formats); err != nil {`, res)
  2271  	}
  2272  }
  2273  
  2274  // This tests makes sure marshalling and validation is generated in aliased formatted definitions
  2275  func TestGenModel_Issue946(t *testing.T) {
  2276  	specDoc, err := loads.Spec("../fixtures/bugs/946/fixture-946.yaml")
  2277  	require.NoError(t, err)
  2278  
  2279  	definitions := specDoc.Spec().Definitions
  2280  	k := "mydate"
  2281  	schema := definitions[k]
  2282  	opts := opts()
  2283  	genModel, err := makeGenDefinition(k, "models", schema, specDoc, opts)
  2284  	require.NoError(t, err)
  2285  
  2286  	buf := bytes.NewBuffer(nil)
  2287  	require.NoError(t, opts.templates.MustGet("model").Execute(buf, genModel))
  2288  
  2289  	ct, err := opts.LanguageOpts.FormatContent("foo.go", buf.Bytes())
  2290  	require.NoError(t, err)
  2291  
  2292  	res := string(ct)
  2293  	assertInCode(t, `type Mydate strfmt.Date`, res)
  2294  	assertInCode(t, `func (m *Mydate) UnmarshalJSON(b []byte) error {`, res)
  2295  	assertInCode(t, `return ((*strfmt.Date)(m)).UnmarshalJSON(b)`, res)
  2296  	assertInCode(t, `func (m Mydate) MarshalJSON() ([]byte, error) {`, res)
  2297  	assertInCode(t, `return (strfmt.Date(m)).MarshalJSON()`, res)
  2298  	assertInCode(t, `if err := validate.FormatOf("", "body", "date", strfmt.Date(m).String(), formats); err != nil {`, res)
  2299  }
  2300  
  2301  // This tests makes sure that docstring in inline schema in response properly reflect the Required property
  2302  func TestGenModel_Issue910(t *testing.T) {
  2303  	specDoc, err := loads.Spec("../fixtures/bugs/910/fixture-910.yaml")
  2304  	require.NoError(t, err)
  2305  
  2306  	p, ok := specDoc.Spec().Paths.Paths["/mytest"]
  2307  	require.True(t, ok)
  2308  
  2309  	op := p.Get
  2310  	responses := op.Responses.StatusCodeResponses
  2311  	for k, r := range responses {
  2312  		t.Logf("Response: %d", k)
  2313  		schema := *r.Schema
  2314  		opts := opts()
  2315  		genModel, err := makeGenDefinition("GetMyTestOKBody", "models", schema, specDoc, opts)
  2316  		require.NoError(t, err)
  2317  
  2318  		buf := bytes.NewBuffer(nil)
  2319  		require.NoError(t, opts.templates.MustGet("model").Execute(buf, genModel))
  2320  
  2321  		ct, err := opts.LanguageOpts.FormatContent("foo.go", buf.Bytes())
  2322  		require.NoError(t, err)
  2323  
  2324  		res := string(ct)
  2325  		assertInCode(t, "// bar\n	// Required: true\n	Bar *int64 `json:\"bar\"`", res)
  2326  		assertInCode(t, "// foo\n	// Required: true\n	Foo interface{} `json:\"foo\"`", res)
  2327  		assertInCode(t, "// baz\n	Baz int64 `json:\"baz,omitempty\"`", res)
  2328  		assertInCode(t, "// quux\n	Quux []string `json:\"quux\"`", res)
  2329  		assertInCode(t, `if err := validate.Required("bar", "body", m.Bar); err != nil {`, res)
  2330  		assertInCode(t, `if m.Foo == nil {`, res) // interface{} now checked against nil (validate.Required fails on any zero value)
  2331  		assertNotInCode(t, `if err := validate.Required("baz", "body", m.Baz); err != nil {`, res)
  2332  		assertNotInCode(t, `if err := validate.Required("quux", "body", m.Quux); err != nil {`, res)
  2333  		// NOTE(fredbi); fixed Required in slices. This property has actually no validation
  2334  	}
  2335  }
  2336  
  2337  func TestGenerateModel_Xorder(t *testing.T) {
  2338  	specDoc, err := loads.Spec("../fixtures/codegen/x-order.yml")
  2339  	require.NoError(t, err)
  2340  
  2341  	definitions := specDoc.Spec().Definitions
  2342  	k := "sessionData"
  2343  	schema := definitions[k]
  2344  	opts := opts()
  2345  	genModel, err := makeGenDefinition(k, "models", schema, specDoc, opts)
  2346  	require.NoError(t, err)
  2347  
  2348  	buf := bytes.NewBuffer(nil)
  2349  	require.NoError(t, opts.templates.MustGet("model").Execute(buf, genModel))
  2350  
  2351  	ff, err := opts.LanguageOpts.FormatContent("x-order.go", buf.Bytes())
  2352  	require.NoError(t, err)
  2353  
  2354  	res := string(ff)
  2355  	// if no x-order then alphabetical order, like DeviceID, SessionID, UMain.
  2356  	// There is x-order
  2357  	//   sessionId
  2358  	//     x-order: 0
  2359  	//   deviceId:
  2360  	//     x-order: 1
  2361  	//   uMain:
  2362  	//     x-order: 2
  2363  	// This is need for msgpack-array.
  2364  	foundDeviceID := strings.Index(res, "DeviceID")
  2365  	foundSessionID := strings.Index(res, "SessionID")
  2366  	foundUMain := strings.Index(res, "UMain")
  2367  	foundAaa := strings.Index(res, "Aaa")
  2368  	foundBbb := strings.Index(res, "Bbb")
  2369  	foundZzz := strings.Index(res, "Zzz")
  2370  	assert.Less(t, foundSessionID, foundDeviceID)
  2371  	assert.Less(t, foundSessionID, foundUMain)
  2372  	assert.Less(t, foundUMain, foundAaa)
  2373  	assert.Less(t, foundAaa, foundBbb)
  2374  	assert.Less(t, foundBbb, foundZzz)
  2375  }
  2376  
  2377  func TestGenModel_Issue1623(t *testing.T) {
  2378  	specDoc, err := loads.Spec("../fixtures/enhancements/1623/swagger.yml")
  2379  	require.NoError(t, err)
  2380  
  2381  	definitions := specDoc.Spec().Definitions
  2382  	k := "Foo"
  2383  	schema := definitions[k]
  2384  	opts := opts()
  2385  
  2386  	genModel, err := makeGenDefinition(k, "models", schema, specDoc, opts)
  2387  	require.NoError(t, err)
  2388  
  2389  	buf := bytes.NewBuffer(nil)
  2390  	require.NoError(t, opts.templates.MustGet("model").Execute(buf, genModel))
  2391  
  2392  	ff, err := opts.LanguageOpts.FormatContent("Foo.go", buf.Bytes())
  2393  	require.NoError(t, err)
  2394  
  2395  	res := string(ff)
  2396  	assertInCode(t, "ArrayHasOmitEmptyFalse []string `json:\"arrayHasOmitEmptyFalse\"`", res)
  2397  	assertInCode(t, "ArrayHasOmitEmptyTrue []string `json:\"arrayHasOmitEmptyTrue,omitempty\"`", res)
  2398  	assertInCode(t, "ArrayNoOmitEmpty []string `json:\"arrayNoOmitEmpty\"`", res)
  2399  	assertInCode(t, "GeneralHasOmitEmptyFalse string `json:\"generalHasOmitEmptyFalse\"`", res)
  2400  	assertInCode(t, "GeneralHasOmitEmptyTrue string `json:\"generalHasOmitEmptyTrue,omitempty\"`", res)
  2401  	assertInCode(t, "GeneralNoOmitEmpty string `json:\"generalNoOmitEmpty,omitempty\"`", res)
  2402  	assertInCode(t, "RefHasOmitEmptyFalse Bar `json:\"refHasOmitEmptyFalse,omitempty\"`", res)
  2403  	assertInCode(t, "RefHasOmitEmptyTrue Bar `json:\"refHasOmitEmptyTrue,omitempty\"`", res)
  2404  	assertInCode(t, "RefNoOmitEmpty Bar `json:\"refNoOmitEmpty,omitempty\"`", res)
  2405  	assertInCode(t, "IntHasJSONString int64 `json:\"intHasJsonString,omitempty,string\"`", res)
  2406  	assertInCode(t, "BoolHasJSONString bool `json:\"boolHasJsonString,omitempty,string\"`", res)
  2407  }
  2408  
  2409  func TestGenerateModel_Issue2457(t *testing.T) {
  2410  	specDoc, err := loads.Spec("../fixtures/bugs/2457/fixture-2457.yaml")
  2411  	require.NoError(t, err)
  2412  
  2413  	definitions := specDoc.Spec().Definitions
  2414  	k := "ObjWithCustomTag"
  2415  	schema := definitions[k]
  2416  	opts := opts()
  2417  	genModel, err := makeGenDefinition(k, "models", schema, specDoc, opts)
  2418  	require.NoError(t, err)
  2419  
  2420  	buf := bytes.NewBuffer(nil)
  2421  	require.NoError(t, opts.templates.MustGet("model").Execute(buf, genModel))
  2422  
  2423  	assertInCode(t, "myobjtag:\"foo,bar\"", buf.String())
  2424  }
  2425  
  2426  func TestGenModel_Pr2464(t *testing.T) {
  2427  	specDoc, err := loads.Spec("../fixtures/enhancements/2464/fixture-2464.yaml")
  2428  	require.NoError(t, err)
  2429  
  2430  	definitions := specDoc.Spec().Definitions
  2431  
  2432  	tests := map[string]struct {
  2433  		model    string
  2434  		expected []string
  2435  	}{
  2436  		"withDot": {
  2437  			model: "band",
  2438  			expected: []string{
  2439  				`BandNr2Dot4Ghz Band = "2.4Ghz"`,
  2440  				`BandNr24Ghz Band = "24Ghz"`,
  2441  			},
  2442  		},
  2443  		"withSigns": {
  2444  			model: "change",
  2445  			expected: []string{
  2446  				`ChangeDash1 Change = "-1"`,
  2447  				`ChangeNr0 Change = "0"`,
  2448  				`ChangePlus1 Change = "+1"`,
  2449  			},
  2450  		},
  2451  		"hashtag": {
  2452  			model: "topic",
  2453  			expected: []string{
  2454  				`TopicHashtagOne Topic = "#one"`,
  2455  				`TopicTwoHashtagTwo Topic = "two#two"`,
  2456  			},
  2457  		},
  2458  	}
  2459  
  2460  	for name, spec := range tests {
  2461  		t.Run(name, func(t *testing.T) {
  2462  			k := spec.model
  2463  			schema := definitions[k]
  2464  			opts := opts()
  2465  			genModel, err := makeGenDefinition(k, "models", schema, specDoc, opts)
  2466  			require.NoError(t, err)
  2467  
  2468  			buf := bytes.NewBuffer(nil)
  2469  			require.NoError(t, opts.templates.MustGet("model").Execute(buf, genModel))
  2470  
  2471  			for _, expected := range spec.expected {
  2472  				assertInCode(t, expected, buf.String())
  2473  			}
  2474  		})
  2475  	}
  2476  }
  2477  
  2478  func TestGenModel_KeepSpecPropertiesOrder(t *testing.T) {
  2479  	ymlFile := "../fixtures/codegen/keep-spec-order.yml"
  2480  	opts := opts()
  2481  	abcType := "abctype"
  2482  
  2483  	specDoc, err := loads.Spec(ymlFile)
  2484  	require.NoError(t, err)
  2485  
  2486  	orderedSpecDoc, err := loads.Spec(WithAutoXOrder(ymlFile))
  2487  	require.NoError(t, err)
  2488  
  2489  	definitions := specDoc.Spec().Definitions
  2490  	orderedDefinitions := orderedSpecDoc.Spec().Definitions
  2491  
  2492  	genModel, err := makeGenDefinition(abcType, "models", definitions[abcType], specDoc, opts)
  2493  	require.NoError(t, err)
  2494  	orderGenModel, err := makeGenDefinition(abcType, "models", orderedDefinitions[abcType], orderedSpecDoc, opts)
  2495  	require.NoError(t, err)
  2496  
  2497  	buf := bytes.NewBuffer(nil)
  2498  	require.NoError(t, opts.templates.MustGet("model").Execute(buf, genModel))
  2499  
  2500  	orderBuf := bytes.NewBuffer(nil)
  2501  	require.NoError(t, opts.templates.MustGet("model").Execute(orderBuf, orderGenModel))
  2502  
  2503  	ff, err := opts.LanguageOpts.FormatContent("keepSpecOrder.go", buf.Bytes())
  2504  	require.NoError(t, err)
  2505  
  2506  	modelCode := string(ff)
  2507  	ff, err = opts.LanguageOpts.FormatContent("keepSpecOrder-ordered.go", orderBuf.Bytes())
  2508  	require.NoError(t, err)
  2509  
  2510  	orderModelCode := string(ff)
  2511  
  2512  	// without auto order, properties sorted by alphanumeric
  2513  	foundA := strings.Index(modelCode, "Aaa")
  2514  	foundB := strings.Index(modelCode, "Bbb")
  2515  	foundC := strings.Index(modelCode, "Ccc")
  2516  	assert.Less(t, foundA, foundB)
  2517  	assert.Less(t, foundB, foundC)
  2518  
  2519  	foundOrderA := strings.Index(orderModelCode, "Aaa")
  2520  	foundOrderB := strings.Index(orderModelCode, "Bbb")
  2521  	foundOrderC := strings.Index(orderModelCode, "Ccc")
  2522  
  2523  	assert.Less(t, foundOrderC, foundOrderB)
  2524  	assert.Less(t, foundOrderB, foundOrderA)
  2525  
  2526  	foundInnerA := strings.Index(modelCode, "InnerAaa")
  2527  	foundInnerB := strings.Index(modelCode, "InnerBbb")
  2528  	foundInnerC := strings.Index(modelCode, "InnerCcc")
  2529  	assert.Less(t, foundInnerA, foundInnerB)
  2530  	assert.Less(t, foundInnerB, foundInnerC)
  2531  
  2532  	foundOrderInnerA := strings.Index(orderModelCode, "InnerAaa")
  2533  	foundOrderInnerB := strings.Index(orderModelCode, "InnerBbb")
  2534  	foundOrderInnerC := strings.Index(orderModelCode, "InnerCcc")
  2535  
  2536  	assert.Less(t, foundOrderInnerC, foundOrderInnerB)
  2537  	assert.Less(t, foundOrderInnerB, foundOrderInnerA)
  2538  }
  2539  
  2540  func TestGenModel_StrictAdditionalProperties(t *testing.T) {
  2541  	specDoc, err := loads.Spec("../fixtures/codegen/strict-additional-properties.yml")
  2542  	require.NoError(t, err)
  2543  
  2544  	definitions := specDoc.Spec().Definitions
  2545  	k := "Body"
  2546  	schema := definitions[k]
  2547  	opts := opts()
  2548  
  2549  	opts.StrictAdditionalProperties = true
  2550  
  2551  	genModel, err := makeGenDefinition(k, "models", schema, specDoc, opts)
  2552  	require.NoError(t, err)
  2553  
  2554  	buf := bytes.NewBuffer(nil)
  2555  	require.NoError(t, opts.templates.MustGet("model").Execute(buf, genModel))
  2556  
  2557  	ff, err := opts.LanguageOpts.FormatContent("strictAdditionalProperties.go", buf.Bytes())
  2558  	require.NoError(t, err)
  2559  
  2560  	res := string(ff)
  2561  	for _, tt := range []struct {
  2562  		name      string
  2563  		assertion func(testing.TB, string, string) bool
  2564  	}{
  2565  		{k, assertInCode},
  2566  		{k + "Explicit", assertInCode},
  2567  		{k + "Implicit", assertInCode},
  2568  		{k + "Disabled", assertNotInCode},
  2569  	} {
  2570  		fn := funcBody(res, "*"+tt.name+") UnmarshalJSON(data []byte) error")
  2571  		if assert.NotEmpty(t, fn, "Method UnmarshalJSON should be defined for type *"+tt.name) {
  2572  			tt.assertion(t, "dec.DisallowUnknownFields()", fn)
  2573  		}
  2574  	}
  2575  }
  2576  
  2577  func TestGenModel_XMLStructTags_WithXML(t *testing.T) {
  2578  	specDoc, err := loads.Spec("../fixtures/codegen/xml-model.yml")
  2579  	require.NoError(t, err)
  2580  
  2581  	definitions := specDoc.Spec().Definitions
  2582  	k := "XmlWithAttribute"
  2583  	opts := opts()
  2584  	opts.WithXML = true
  2585  
  2586  	genModel, err := makeGenDefinition(k, "models", definitions[k], specDoc, opts)
  2587  	require.NoError(t, err)
  2588  
  2589  	buf := bytes.NewBuffer(nil)
  2590  	require.NoError(t, opts.templates.MustGet("model").Execute(buf, genModel))
  2591  
  2592  	ct, err := opts.LanguageOpts.FormatContent("xml_with_attribute.go", buf.Bytes())
  2593  	require.NoError(t, err)
  2594  
  2595  	res := string(ct)
  2596  	assertInCode(t, "Author *string `json:\"author\" xml:\"author\"`", res)
  2597  	assertInCode(t, "Children []*XMLChild `json:\"children\" xml:\"children\"`", res)
  2598  	assertInCode(t, "ID int64 `json:\"id,omitempty\" xml:\"id,attr,omitempty\"`", res)
  2599  	assertInCode(t, "IsPublished *bool `json:\"isPublished\" xml:\"published,attr\"`", res)
  2600  	assertInCode(t, "SingleChild *XMLChild `json:\"singleChild,omitempty\" xml:\"singleChild,omitempty\"`", res)
  2601  	assertInCode(t, "Title string `json:\"title,omitempty\" xml:\"xml-title,omitempty\"`", res)
  2602  }
  2603  
  2604  func TestGenModel_XMLStructTags_Explicit(t *testing.T) {
  2605  	specDoc, err := loads.Spec("../fixtures/codegen/xml-model.yml")
  2606  	require.NoError(t, err)
  2607  
  2608  	definitions := specDoc.Spec().Definitions
  2609  	k := "XmlWithAttribute"
  2610  	opts := opts()
  2611  
  2612  	genModel, err := makeGenDefinition(k, "models", definitions[k], specDoc, opts)
  2613  	require.NoError(t, err)
  2614  
  2615  	buf := bytes.NewBuffer(nil)
  2616  	require.NoError(t, opts.templates.MustGet("model").Execute(buf, genModel))
  2617  
  2618  	ct, err := opts.LanguageOpts.FormatContent("xml_with_attribute.go", buf.Bytes())
  2619  	require.NoErrorf(t, err, "format error: %v\n%s", err, buf.String())
  2620  
  2621  	res := string(ct)
  2622  	assertInCode(t, "Author *string `json:\"author\"`", res)
  2623  	assertInCode(t, "Children []*XMLChild `json:\"children\"`", res)
  2624  	assertInCode(t, "ID int64 `json:\"id,omitempty\" xml:\"id,attr,omitempty\"`", res)
  2625  	assertInCode(t, "IsPublished *bool `json:\"isPublished\" xml:\"published,attr\"`", res)
  2626  	assertInCode(t, "SingleChild *XMLChild `json:\"singleChild,omitempty\"`", res)
  2627  	assertInCode(t, "Title string `json:\"title,omitempty\" xml:\"xml-title,omitempty\"`", res)
  2628  }
  2629  
  2630  func TestGenerateModels(t *testing.T) {
  2631  	t.Parallel()
  2632  	defer discardOutput()()
  2633  
  2634  	cwd := testCwd(t)
  2635  	const root = "generated_models"
  2636  	defer func() {
  2637  		_ = os.RemoveAll(filepath.Join(cwd, root))
  2638  	}()
  2639  
  2640  	t.Run("generate models", func(t *testing.T) {
  2641  		cases := map[string]generateFixture{
  2642  			"allDefinitions": {
  2643  				spec:   "../fixtures/bugs/1042/fixture-1042.yaml",
  2644  				target: "../fixtures/bugs/1042",
  2645  				verify: func(t *testing.T, target string) {
  2646  					target = filepath.Join(target, defaultModelsTarget)
  2647  					require.True(t, fileExists(target, ""))
  2648  					assert.True(t, fileExists(target, "a.go"))
  2649  					assert.True(t, fileExists(target, "b.go"))
  2650  				},
  2651  			},
  2652  			"acceptDefinitions": {
  2653  				spec:   "../fixtures/enhancements/2333/fixture-definitions.yaml",
  2654  				target: "../fixtures/enhancements/2333",
  2655  				prepare: func(_ *testing.T, opts *GenOpts) {
  2656  					opts.AcceptDefinitionsOnly = true
  2657  				},
  2658  				verify: func(t *testing.T, target string) {
  2659  					target = filepath.Join(target, defaultModelsTarget)
  2660  					require.True(t, fileExists(target, ""))
  2661  					assert.True(t, fileExists(target, "model_interface.go"))
  2662  					assert.True(t, fileExists(target, "records_model.go"))
  2663  					assert.True(t, fileExists(target, "records_model_with_max.go"))
  2664  					assert.False(t, fileExists(target, "restapi"))
  2665  				},
  2666  			},
  2667  			"mangleNames": {
  2668  				spec:   "../fixtures/bugs/2821/ServiceManagementBody.json",
  2669  				target: "../fixtures/bugs/2821",
  2670  				verify: func(t *testing.T, target string) {
  2671  					target = filepath.Join(target, defaultModelsTarget)
  2672  					require.True(t, fileExists(target, "schema.go"))
  2673  					content, err := os.ReadFile(filepath.Join(target, "schema.go"))
  2674  					require.NoError(t, err)
  2675  					assert.Contains(t, string(content), "getDollarRefField string")
  2676  				},
  2677  			},
  2678  		}
  2679  		for k, cas := range cases {
  2680  			name := k
  2681  			thisCas := cas
  2682  
  2683  			t.Run(name, func(t *testing.T) {
  2684  				t.Parallel()
  2685  
  2686  				defer thisCas.warnFailed(t)
  2687  
  2688  				opts := testGenOpts()
  2689  				defer thisCas.prepareTarget(t, name, "model_test", root, opts)()
  2690  
  2691  				if thisCas.prepare != nil {
  2692  					thisCas.prepare(t, opts)
  2693  				}
  2694  
  2695  				t.Run(fmt.Sprintf("generating test models from: %s", opts.Spec), func(t *testing.T) {
  2696  					err := GenerateModels([]string{"", ""}, opts) // NOTE: generate all models, ignore ""
  2697  					if thisCas.wantError {
  2698  						require.Errorf(t, err, "expected an error for models build fixture: %s", opts.Spec)
  2699  					} else {
  2700  						require.NoError(t, err, "unexpected error for models build fixture: %s", opts.Spec)
  2701  					}
  2702  
  2703  					if thisCas.verify != nil {
  2704  						thisCas.verify(t, opts.Target)
  2705  					}
  2706  				})
  2707  			})
  2708  		}
  2709  	})
  2710  }
  2711  
  2712  func Test_PointerConversions(t *testing.T) {
  2713  	// generation of a pointer converter for enum vars
  2714  	specDoc, err := loads.Spec("../fixtures/bugs/252/swagger.json")
  2715  	require.NoError(t, err)
  2716  
  2717  	definitions := specDoc.Spec().Definitions
  2718  	k := "SodaBrand"
  2719  	opts := opts()
  2720  	genModel, err := makeGenDefinition(k, "models", definitions[k], specDoc, opts)
  2721  	require.NoError(t, err)
  2722  	require.False(t, genModel.IsNullable)
  2723  
  2724  	buf := bytes.NewBuffer(nil)
  2725  	require.NoError(t, opts.templates.MustGet("model").Execute(buf, genModel))
  2726  
  2727  	ct, err := opts.LanguageOpts.FormatContent("soda_brand.go", buf.Bytes())
  2728  	require.NoError(t, err)
  2729  
  2730  	res := string(ct)
  2731  	funcLines := [][]string{
  2732  		{
  2733  			"func NewSodaBrand(value SodaBrand) *SodaBrand {",
  2734  			"\treturn &value",
  2735  			"}",
  2736  		},
  2737  		{
  2738  			"func (m SodaBrand) Pointer() *SodaBrand {",
  2739  			"\treturn &m",
  2740  			"}",
  2741  		},
  2742  	}
  2743  	for _, f := range funcLines {
  2744  		joined := strings.Join(f, "\n")
  2745  		assert.Contains(t, res, joined)
  2746  	}
  2747  }
  2748  
  2749  func TestIssue2597(t *testing.T) {
  2750  	specDoc, err := loads.Spec("../fixtures/bugs/2597/2597.yaml")
  2751  	require.NoError(t, err)
  2752  
  2753  	const antipattern = `(validate\.\w+\("",\s+"body",.+?\))|(errors\.\w+\("",\s+"body",.+?\))`
  2754  	definitions := specDoc.Spec().Definitions
  2755  
  2756  	t.Run("with RootedErrorPath option", func(t *testing.T) {
  2757  		opts := opts()
  2758  		opts.WantsRootedErrorPath = true
  2759  
  2760  		t.Run("should generate the extra path for arrays and maps", func(t *testing.T) {
  2761  			for _, model := range []string{
  2762  				"BlahArray",
  2763  				"BlahComplexArray",
  2764  				"BlahMap",
  2765  				"BlahComplexMap",
  2766  			} {
  2767  				pattern := fmt.Sprintf(`(validate\.\w+\("\[%[1]s\]",\s+"body",.+?\))|(errors\.\w+\("\[%[1]s\]",\s+"body",.+?\))`, model)
  2768  				genModel, err := makeGenDefinition(model, "models", definitions[model], specDoc, opts)
  2769  				require.NoError(t, err)
  2770  
  2771  				buf := bytes.NewBuffer(nil)
  2772  				require.NoError(t, opts.templates.MustGet("model").Execute(buf, genModel))
  2773  
  2774  				ct, err := opts.LanguageOpts.FormatContent("model.go", buf.Bytes())
  2775  				require.NoErrorf(t, err, "format error: %v\n%s", err, buf.String())
  2776  
  2777  				res := string(ct)
  2778  				assertRegexpInCode(t, pattern, res)
  2779  				assertRegexpNotInCode(t, antipattern, res)
  2780  			}
  2781  		})
  2782  
  2783  		t.Run("should NOT generate the extra path for structs", func(t *testing.T) {
  2784  			const model = "BlahStruct"
  2785  			pattern := fmt.Sprintf(`(validate\.\w+\("\[%[1]s\]",\s+"body",.+?\))|(errors\.\w+\("\[%[1]s\]",\s+"body",.+?\))`, model)
  2786  
  2787  			genModel, err := makeGenDefinition(model, "models", definitions[model], specDoc, opts)
  2788  			require.NoError(t, err)
  2789  
  2790  			buf := bytes.NewBuffer(nil)
  2791  			require.NoError(t, opts.templates.MustGet("model").Execute(buf, genModel))
  2792  
  2793  			ct, err := opts.LanguageOpts.FormatContent("model.go", buf.Bytes())
  2794  			require.NoErrorf(t, err, "format error: %v\n%s", err, buf.String())
  2795  
  2796  			res := string(ct)
  2797  			assertRegexpNotInCode(t, pattern, res)
  2798  			assertRegexpNotInCode(t, antipattern, res) // we have a path, that is the property name
  2799  		})
  2800  	})
  2801  
  2802  	t.Run("without RootedErrorPath option", func(t *testing.T) {
  2803  		opts := opts()
  2804  
  2805  		t.Run("should NOT generate the extra path for arrays and maps", func(t *testing.T) {
  2806  			for _, model := range []string{
  2807  				"BlahArray",
  2808  				"BlahComplexArray",
  2809  				"BlahMap",
  2810  				"BlahComplexMap",
  2811  			} {
  2812  				pattern := fmt.Sprintf(`(validate\.\w+\("\[%[1]s\]",\s+"body",.+?\))|(errors\.\w+\("\[%[1]s\]",\s+"body",.+?\))`, model)
  2813  				genModel, err := makeGenDefinition(model, "models", definitions[model], specDoc, opts)
  2814  				require.NoError(t, err)
  2815  
  2816  				buf := bytes.NewBuffer(nil)
  2817  				require.NoError(t, opts.templates.MustGet("model").Execute(buf, genModel))
  2818  
  2819  				ct, err := opts.LanguageOpts.FormatContent("model.go", buf.Bytes())
  2820  				require.NoErrorf(t, err, "format error: %v\n%s", err, buf.String())
  2821  
  2822  				res := string(ct)
  2823  				assertRegexpNotInCode(t, pattern, res)
  2824  				assertRegexpInCode(t, antipattern, res)
  2825  			}
  2826  		})
  2827  
  2828  		t.Run("should NOT generate the extra path for structs", func(t *testing.T) {
  2829  			const model = "BlahStruct"
  2830  			pattern := fmt.Sprintf(`(validate\.\w+\("\[%[1]s\]",\s+"body",.+?\))|(errors\.\w+\("\[%[1]s\]",\s+"body",.+?\))`, model)
  2831  
  2832  			genModel, err := makeGenDefinition(model, "models", definitions[model], specDoc, opts)
  2833  			require.NoError(t, err)
  2834  
  2835  			buf := bytes.NewBuffer(nil)
  2836  			require.NoError(t, opts.templates.MustGet("model").Execute(buf, genModel))
  2837  
  2838  			ct, err := opts.LanguageOpts.FormatContent("model.go", buf.Bytes())
  2839  			require.NoErrorf(t, err, "format error: %v\n%s", err, buf.String())
  2840  
  2841  			res := string(ct)
  2842  			assertRegexpNotInCode(t, pattern, res)
  2843  			assertRegexpNotInCode(t, antipattern, res) // we have a path, that is the property name
  2844  		})
  2845  	})
  2846  }