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