github.com/emreu/go-swagger@v0.22.1/generator/schemavalidation_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  	"log"
    21  	"regexp"
    22  	"testing"
    23  
    24  	"github.com/go-openapi/loads"
    25  	"github.com/go-openapi/swag"
    26  	"github.com/stretchr/testify/assert"
    27  )
    28  
    29  func init() {
    30  	log.SetFlags(log.LstdFlags | log.Lshortfile)
    31  }
    32  
    33  func reqm(str string) *regexp.Regexp {
    34  	return regexp.MustCompile(regexp.QuoteMeta(str))
    35  }
    36  
    37  func reqOri(str string) *regexp.Regexp {
    38  	return regexp.MustCompile(str)
    39  }
    40  
    41  func assertInCode(t testing.TB, expr, code string) bool {
    42  	return assert.Regexp(t, reqm(expr), code)
    43  }
    44  
    45  func assertRegexpInCode(t testing.TB, expr, code string) bool {
    46  	return assert.Regexp(t, reqOri(expr), code)
    47  }
    48  
    49  func assertNotInCode(t testing.TB, expr, code string) bool {
    50  	return assert.NotRegexp(t, reqm(expr), code)
    51  }
    52  
    53  // Unused
    54  // func assertRegexpNotInCode(t testing.TB, expr, code string) bool {
    55  // 	return assert.NotRegexp(t, reqOri(expr), code)
    56  // }
    57  
    58  func assertValidation(t testing.TB, pth, expr string, gm GenSchema) bool {
    59  	if !assert.True(t, gm.HasValidations, "expected the schema to have validations") {
    60  		return false
    61  	}
    62  	if !assert.Equal(t, pth, gm.Path, "paths don't match") {
    63  		return false
    64  	}
    65  	if !assert.Equal(t, expr, gm.ValueExpression, "expressions don't match") {
    66  		return false
    67  	}
    68  	return true
    69  }
    70  
    71  func funcBody(code string, signature string) string {
    72  	submatches := regexp.MustCompile(
    73  		"\\nfunc \\([a-zA-Z_][a-zA-Z0-9_]* " + regexp.QuoteMeta(signature) + " {\\n" + // function signature
    74  			"((([^}\\n][^\\n]*)?\\n)*)}\\n", // function body
    75  	).FindStringSubmatch(code)
    76  
    77  	if submatches == nil {
    78  		return ""
    79  	}
    80  	return submatches[1]
    81  }
    82  
    83  func TestSchemaValidation_RequiredProps(t *testing.T) {
    84  	specDoc, err := loads.Spec("../fixtures/codegen/todolist.schemavalidation.yml")
    85  	if assert.NoError(t, err) {
    86  		k := "RequiredProps"
    87  		schema := specDoc.Spec().Definitions[k]
    88  
    89  		opts := opts()
    90  		gm, err := makeGenDefinition(k, "models", schema, specDoc, opts)
    91  		if assert.NoError(t, err) {
    92  			assert.Len(t, gm.Properties, 6)
    93  			for _, p := range gm.Properties {
    94  				if assert.True(t, p.Required) {
    95  					buf := bytes.NewBuffer(nil)
    96  					err := templates.MustGet("model").Execute(buf, gm)
    97  					if assert.NoError(t, err) {
    98  						formatted, err := opts.LanguageOpts.FormatContent("required_props.go", buf.Bytes())
    99  						if assert.NoError(t, err) {
   100  							res := string(formatted)
   101  							assertInCode(t, k+") Validate(formats", res)
   102  							assertInCode(t, "validate"+swag.ToGoName(p.Name), res)
   103  							assertInCode(t, "err := validate.Required", res)
   104  							assertInCode(t, "errors.CompositeValidationError(res...)", res)
   105  						}
   106  					}
   107  				}
   108  			}
   109  		}
   110  	}
   111  }
   112  
   113  func TestSchemaValidation_Strings(t *testing.T) {
   114  	specDoc, err := loads.Spec("../fixtures/codegen/todolist.schemavalidation.yml")
   115  	if assert.NoError(t, err) {
   116  		k := "NamedString"
   117  		schema := specDoc.Spec().Definitions[k]
   118  
   119  		opts := opts()
   120  		gm, err := makeGenDefinition(k, "models", schema, specDoc, opts)
   121  		if assert.NoError(t, err) {
   122  			if assertValidation(t, "", "m", gm.GenSchema) {
   123  				buf := bytes.NewBuffer(nil)
   124  				err := templates.MustGet("model").Execute(buf, gm)
   125  				if assert.NoError(t, err) {
   126  					formatted, err := opts.LanguageOpts.FormatContent("named_string.go", buf.Bytes())
   127  					if assert.NoError(t, err) {
   128  						res := string(formatted)
   129  						assertInCode(t, k+") Validate(formats", res)
   130  						assertInCode(t, "err := validate.MinLength", res)
   131  						assertInCode(t, "err := validate.MaxLength", res)
   132  						assertInCode(t, "err := validate.Pattern", res)
   133  						assertInCode(t, "errors.CompositeValidationError(res...)", res)
   134  					}
   135  				}
   136  			}
   137  		}
   138  	}
   139  }
   140  
   141  func TestSchemaValidation_StringProps(t *testing.T) {
   142  	specDoc, err := loads.Spec("../fixtures/codegen/todolist.schemavalidation.yml")
   143  	if assert.NoError(t, err) {
   144  		k := "StringValidations"
   145  		schema := specDoc.Spec().Definitions[k]
   146  
   147  		opts := opts()
   148  		gm, err := makeGenDefinition(k, "models", schema, specDoc, opts)
   149  		if assert.NoError(t, err) {
   150  			prop := gm.Properties[0]
   151  			if assertValidation(t, "\"name\"", "m.Name", prop) {
   152  				buf := bytes.NewBuffer(nil)
   153  				err := templates.MustGet("model").Execute(buf, gm)
   154  				if assert.NoError(t, err) {
   155  					formatted, err := opts.LanguageOpts.FormatContent("string_validations.go", buf.Bytes())
   156  					if assert.NoError(t, err) {
   157  						res := string(formatted)
   158  						assertInCode(t, k+") Validate(formats", res)
   159  						assertInCode(t, "m.validateName(formats", res)
   160  						assertInCode(t, "err := validate.MinLength(\"name\",", res)
   161  						assertInCode(t, "err := validate.MaxLength(\"name\",", res)
   162  						assertInCode(t, "err := validate.Pattern(\"name\",", res)
   163  						assertInCode(t, "errors.CompositeValidationError(res...)", res)
   164  					}
   165  				}
   166  			}
   167  		}
   168  	}
   169  }
   170  
   171  func TestSchemaValidation_NamedNumber(t *testing.T) {
   172  	specDoc, err := loads.Spec("../fixtures/codegen/todolist.schemavalidation.yml")
   173  	if assert.NoError(t, err) {
   174  		k := "NamedNumber"
   175  		schema := specDoc.Spec().Definitions[k]
   176  
   177  		opts := opts()
   178  		gm, err := makeGenDefinition(k, "models", schema, specDoc, opts)
   179  		if assert.NoError(t, err) {
   180  			if assertValidation(t, "", "m", gm.GenSchema) {
   181  				buf := bytes.NewBuffer(nil)
   182  				err := templates.MustGet("model").Execute(buf, gm)
   183  				if assert.NoError(t, err) {
   184  					formatted, err := opts.LanguageOpts.FormatContent("named_number.go", buf.Bytes())
   185  					if assert.NoError(t, err) {
   186  						res := string(formatted)
   187  						//fmt.Println(res)
   188  						assertInCode(t, k+") Validate(formats", res)
   189  						assertInCode(t, "err := validate.MinimumInt", res)
   190  						assertInCode(t, "err := validate.MaximumInt", res)
   191  						assertInCode(t, "err := validate.MultipleOf", res)
   192  						assertInCode(t, "errors.CompositeValidationError(res...)", res)
   193  					}
   194  				}
   195  			}
   196  		}
   197  	}
   198  }
   199  
   200  func TestSchemaValidation_NumberProps(t *testing.T) {
   201  	specDoc, err := loads.Spec("../fixtures/codegen/todolist.schemavalidation.yml")
   202  	if assert.NoError(t, err) {
   203  		k := "NumberValidations"
   204  		schema := specDoc.Spec().Definitions[k]
   205  
   206  		opts := opts()
   207  		gm, err := makeGenDefinition(k, "models", schema, specDoc, opts)
   208  		if assert.NoError(t, err) {
   209  			prop := gm.Properties[0]
   210  			if assertValidation(t, "\"age\"", "m.Age", prop) {
   211  				buf := bytes.NewBuffer(nil)
   212  				err := templates.MustGet("model").Execute(buf, gm)
   213  				if assert.NoError(t, err) {
   214  					formatted, err := opts.LanguageOpts.FormatContent("number_validations.go", buf.Bytes())
   215  					if assert.NoError(t, err) {
   216  						res := string(formatted)
   217  						assertInCode(t, k+") Validate(formats", res)
   218  						assertInCode(t, "m.validateAge(formats", res)
   219  						assertInCode(t, "err := validate.MinimumInt(\"age\",", res)
   220  						assertInCode(t, "err := validate.MaximumInt(\"age\",", res)
   221  						assertInCode(t, "err := validate.MultipleOf(\"age\",", res)
   222  						assertInCode(t, "errors.CompositeValidationError(res...)", res)
   223  					}
   224  				}
   225  			}
   226  		}
   227  	}
   228  }
   229  
   230  func TestSchemaValidation_NamedArray(t *testing.T) {
   231  	specDoc, err := loads.Spec("../fixtures/codegen/todolist.schemavalidation.yml")
   232  	if assert.NoError(t, err) {
   233  		k := "NamedArray"
   234  		schema := specDoc.Spec().Definitions[k]
   235  
   236  		opts := opts()
   237  		gm, err := makeGenDefinition(k, "models", schema, specDoc, opts)
   238  		if assert.NoError(t, err) {
   239  			if assertValidation(t, "", "m", gm.GenSchema) {
   240  				buf := bytes.NewBuffer(nil)
   241  				err := templates.MustGet("model").Execute(buf, gm)
   242  				if assert.NoError(t, err) {
   243  					formatted, err := opts.LanguageOpts.FormatContent("named_array.go", buf.Bytes())
   244  					if assert.NoError(t, err) {
   245  						res := string(formatted)
   246  						assertInCode(t, k+") Validate(formats", res)
   247  						assertInCode(t, "err := validate.MinItems(\"\"", res)
   248  						assertInCode(t, "err := validate.MaxItems(\"\"", res)
   249  						assertInCode(t, "err := validate.MinLength(strconv.Itoa(i),", res)
   250  						assertInCode(t, "err := validate.MaxLength(strconv.Itoa(i),", res)
   251  						assertInCode(t, "err := validate.Pattern(strconv.Itoa(i),", res)
   252  						assertInCode(t, "errors.CompositeValidationError(res...)", res)
   253  					}
   254  				}
   255  			}
   256  		}
   257  	}
   258  }
   259  
   260  func TestSchemaValidation_ArrayProps(t *testing.T) {
   261  	specDoc, err := loads.Spec("../fixtures/codegen/todolist.schemavalidation.yml")
   262  	if assert.NoError(t, err) {
   263  		k := "ArrayValidations"
   264  		schema := specDoc.Spec().Definitions[k]
   265  
   266  		opts := opts()
   267  		gm, err := makeGenDefinition(k, "models", schema, specDoc, opts)
   268  		if assert.NoError(t, err) {
   269  			prop := gm.Properties[0]
   270  			if assertValidation(t, "\"tags\"", "m.Tags", prop) {
   271  				buf := bytes.NewBuffer(nil)
   272  				err := templates.MustGet("model").Execute(buf, gm)
   273  				if assert.NoError(t, err) {
   274  					formatted, err := opts.LanguageOpts.FormatContent("array_validations.go", buf.Bytes())
   275  					if assert.NoError(t, err) {
   276  						res := string(formatted)
   277  						assertInCode(t, k+") Validate(formats", res)
   278  						assertInCode(t, "m.validateTags(formats", res)
   279  						assertInCode(t, "err := validate.MinItems(\"tags\"", res)
   280  						assertInCode(t, "err := validate.MaxItems(\"tags\"", res)
   281  						assertInCode(t, "err := validate.MinLength(\"tags\"+\".\"+strconv.Itoa(i),", res)
   282  						assertInCode(t, "err := validate.MaxLength(\"tags\"+\".\"+strconv.Itoa(i),", res)
   283  						assertInCode(t, "err := validate.Pattern(\"tags\"+\".\"+strconv.Itoa(i),", res)
   284  						assertInCode(t, "errors.CompositeValidationError(res...)", res)
   285  					}
   286  				}
   287  			}
   288  		}
   289  	}
   290  }
   291  
   292  func TestSchemaValidation_NamedNestedArray(t *testing.T) {
   293  	specDoc, err := loads.Spec("../fixtures/codegen/todolist.schemavalidation.yml")
   294  	if assert.NoError(t, err) {
   295  		k := "NamedNestedArray"
   296  		schema := specDoc.Spec().Definitions[k]
   297  
   298  		opts := opts()
   299  		gm, err := makeGenDefinition(k, "models", schema, specDoc, opts)
   300  		if assert.NoError(t, err) {
   301  			if assertValidation(t, "", "m", gm.GenSchema) {
   302  				buf := bytes.NewBuffer(nil)
   303  				err := templates.MustGet("model").Execute(buf, gm)
   304  				if assert.NoError(t, err) {
   305  					formatted, err := opts.LanguageOpts.FormatContent("named_nested_array.go", buf.Bytes())
   306  					if assert.NoError(t, err) {
   307  						res := string(formatted)
   308  						assertInCode(t, k+") Validate(formats", res)
   309  						assertInCode(t, "iNamedNestedArraySize := int64(len(m))", res)
   310  						assertInCode(t, "iiNamedNestedArraySize := int64(len(m[i]))", res)
   311  						assertInCode(t, "iiiNamedNestedArraySize := int64(len(m[i][ii]))", res)
   312  						assertInCode(t, "err := validate.MinItems(\"\"", res)
   313  						assertInCode(t, "err := validate.MaxItems(\"\"", res)
   314  						assertInCode(t, "err := validate.MinItems(strconv.Itoa(i),", res)
   315  						assertInCode(t, "err := validate.MaxItems(strconv.Itoa(i),", res)
   316  						assertInCode(t, "err := validate.MinItems(strconv.Itoa(i)+\".\"+strconv.Itoa(ii),", res)
   317  						assertInCode(t, "err := validate.MaxItems(strconv.Itoa(i)+\".\"+strconv.Itoa(ii),", res)
   318  						assertInCode(t, "err := validate.MinLength(strconv.Itoa(i)+\".\"+strconv.Itoa(ii)+\".\"+strconv.Itoa(iii),", res)
   319  						assertInCode(t, "err := validate.MaxLength(strconv.Itoa(i)+\".\"+strconv.Itoa(ii)+\".\"+strconv.Itoa(iii),", res)
   320  						assertInCode(t, "err := validate.Pattern(strconv.Itoa(i)+\".\"+strconv.Itoa(ii)+\".\"+strconv.Itoa(iii),", res)
   321  						assertInCode(t, "errors.CompositeValidationError(res...)", res)
   322  					}
   323  				}
   324  			}
   325  		}
   326  	}
   327  }
   328  
   329  func TestSchemaValidation_NestedArrayProps(t *testing.T) {
   330  	specDoc, err := loads.Spec("../fixtures/codegen/todolist.schemavalidation.yml")
   331  	if assert.NoError(t, err) {
   332  		k := "NestedArrayValidations"
   333  		schema := specDoc.Spec().Definitions[k]
   334  
   335  		opts := opts()
   336  		gm, err := makeGenDefinition(k, "models", schema, specDoc, opts)
   337  		if assert.NoError(t, err) {
   338  			prop := gm.Properties[0]
   339  			if assertValidation(t, "\"tags\"", "m.Tags", prop) {
   340  				buf := bytes.NewBuffer(nil)
   341  				err := templates.MustGet("model").Execute(buf, gm)
   342  				if assert.NoError(t, err) {
   343  					formatted, err := opts.LanguageOpts.FormatContent("nested_array_validations.go", buf.Bytes())
   344  					if assert.NoError(t, err) {
   345  						res := string(formatted)
   346  						assertInCode(t, k+") Validate(formats", res)
   347  						assertInCode(t, "m.validateTags(formats", res)
   348  						assertInCode(t, "iTagsSize := int64(len(m.Tags))", res)
   349  						assertInCode(t, "iiTagsSize := int64(len(m.Tags[i]))", res)
   350  						assertInCode(t, "iiiTagsSize := int64(len(m.Tags[i][ii]))", res)
   351  						assertInCode(t, "err := validate.MinItems(\"tags\"", res)
   352  						assertInCode(t, "err := validate.MaxItems(\"tags\"", res)
   353  						assertInCode(t, "err := validate.MinItems(\"tags\"+\".\"+strconv.Itoa(i),", res)
   354  						assertInCode(t, "err := validate.MaxItems(\"tags\"+\".\"+strconv.Itoa(i),", res)
   355  						assertInCode(t, "err := validate.MinItems(\"tags\"+\".\"+strconv.Itoa(i)+\".\"+strconv.Itoa(ii),", res)
   356  						assertInCode(t, "err := validate.MaxItems(\"tags\"+\".\"+strconv.Itoa(i)+\".\"+strconv.Itoa(ii),", res)
   357  						assertInCode(t, "err := validate.MinLength(\"tags\"+\".\"+strconv.Itoa(i)+\".\"+strconv.Itoa(ii)+\".\"+strconv.Itoa(iii),", res)
   358  						assertInCode(t, "err := validate.MaxLength(\"tags\"+\".\"+strconv.Itoa(i)+\".\"+strconv.Itoa(ii)+\".\"+strconv.Itoa(iii),", res)
   359  						assertInCode(t, "err := validate.Pattern(\"tags\"+\".\"+strconv.Itoa(i)+\".\"+strconv.Itoa(ii)+\".\"+strconv.Itoa(iii),", res)
   360  						assertInCode(t, "errors.CompositeValidationError(res...)", res)
   361  					}
   362  				}
   363  			}
   364  		}
   365  	}
   366  }
   367  
   368  func TestSchemaValidation_NamedNestedObject(t *testing.T) {
   369  	specDoc, err := loads.Spec("../fixtures/codegen/todolist.schemavalidation.yml")
   370  	if assert.NoError(t, err) {
   371  		k := "NamedNestedObject"
   372  		schema := specDoc.Spec().Definitions[k]
   373  
   374  		opts := opts()
   375  		gm, err := makeGenDefinition(k, "models", schema, specDoc, opts)
   376  		if assert.NoError(t, err) {
   377  			if assertValidation(t, "", "m", gm.GenSchema) {
   378  				buf := bytes.NewBuffer(nil)
   379  				err := templates.MustGet("model").Execute(buf, gm)
   380  				if assert.NoError(t, err) {
   381  					formatted, err := opts.LanguageOpts.FormatContent("named_nested_object.go", buf.Bytes())
   382  					if assert.NoError(t, err) {
   383  						res := string(formatted)
   384  						assertInCode(t, k+") Validate(formats", res)
   385  						assertInCode(t, k+"Meta) Validate(formats", res)
   386  						assertInCode(t, k+") validateMeta(formats", res)
   387  						assertInCode(t, "m.Meta.Validate(formats)", res)
   388  						assertInCode(t, "err := validate.MinLength(\"meta\"+\".\"+\"first\",", res)
   389  						assertInCode(t, "err := validate.MaxLength(\"meta\"+\".\"+\"first\",", res)
   390  						assertInCode(t, "err := validate.Pattern(\"meta\"+\".\"+\"first\",", res)
   391  						assertInCode(t, "err := validate.Minimum(\"meta\"+\".\"+\"second\",", res)
   392  						assertInCode(t, "err := validate.Maximum(\"meta\"+\".\"+\"second\",", res)
   393  						assertInCode(t, "err := validate.MultipleOf(\"meta\"+\".\"+\"second\",", res)
   394  						assertInCode(t, "iThirdSize := int64(len(m.Third))", res)
   395  						assertInCode(t, "err := validate.MinItems(\"meta\"+\".\"+\"third\",", res)
   396  						assertInCode(t, "err := validate.MaxItems(\"meta\"+\".\"+\"third\",", res)
   397  						assertInCode(t, "err := validate.Minimum(\"meta\"+\".\"+\"third\"+\".\"+strconv.Itoa(i),", res)
   398  						assertInCode(t, "err := validate.Maximum(\"meta\"+\".\"+\"third\"+\".\"+strconv.Itoa(i),", res)
   399  						assertInCode(t, "err := validate.MultipleOf(\"meta\"+\".\"+\"third\"+\".\"+strconv.Itoa(i),", res)
   400  						assertInCode(t, "iFourthSize := int64(len(m.Fourth))", res)
   401  						assertInCode(t, "iiFourthSize := int64(len(m.Fourth[i]))", res)
   402  						assertInCode(t, "iiiFourthSize := int64(len(m.Fourth[i][ii]))", res)
   403  						assertInCode(t, "err := validate.MinItems(\"meta\"+\".\"+\"fourth\"+\".\"+strconv.Itoa(i),", res)
   404  						assertInCode(t, "err := validate.MaxItems(\"meta\"+\".\"+\"fourth\"+\".\"+strconv.Itoa(i),", res)
   405  						assertInCode(t, "err := validate.MinItems(\"meta\"+\".\"+\"fourth\"+\".\"+strconv.Itoa(i)+\".\"+strconv.Itoa(ii),", res)
   406  						assertInCode(t, "err := validate.MaxItems(\"meta\"+\".\"+\"fourth\"+\".\"+strconv.Itoa(i)+\".\"+strconv.Itoa(ii),", res)
   407  						assertInCode(t, "err := validate.Minimum(\"meta\"+\".\"+\"fourth\"+\".\"+strconv.Itoa(i)+\".\"+strconv.Itoa(ii)+\".\"+strconv.Itoa(iii),", res)
   408  						assertInCode(t, "err := validate.Maximum(\"meta\"+\".\"+\"fourth\"+\".\"+strconv.Itoa(i)+\".\"+strconv.Itoa(ii)+\".\"+strconv.Itoa(iii),", res)
   409  						assertInCode(t, "err := validate.MultipleOf(\"meta\"+\".\"+\"fourth\"+\".\"+strconv.Itoa(i)+\".\"+strconv.Itoa(ii)+\".\"+strconv.Itoa(iii),", res)
   410  						assertInCode(t, "errors.CompositeValidationError(res...)", res)
   411  					}
   412  				}
   413  			}
   414  		}
   415  	}
   416  }
   417  
   418  func TestSchemaValidation_NestedObjectProps(t *testing.T) {
   419  	specDoc, err := loads.Spec("../fixtures/codegen/todolist.schemavalidation.yml")
   420  	if assert.NoError(t, err) {
   421  		k := "NestedObjectValidations"
   422  		schema := specDoc.Spec().Definitions[k]
   423  
   424  		opts := opts()
   425  		gm, err := makeGenDefinition(k, "models", schema, specDoc, opts)
   426  		if assert.NoError(t, err) {
   427  			prop := gm.Properties[0]
   428  			if assertValidation(t, "\"args\"", "m.Args", prop) {
   429  				buf := bytes.NewBuffer(nil)
   430  				err := templates.MustGet("model").Execute(buf, gm)
   431  				if assert.NoError(t, err) {
   432  					formatted, err := opts.LanguageOpts.FormatContent("nested_object_validations.go", buf.Bytes())
   433  					if assert.NoError(t, err) {
   434  						res := string(formatted)
   435  						assertInCode(t, k+") Validate(formats", res)
   436  						assertInCode(t, k+"Args) Validate(formats", res)
   437  						assertInCode(t, k+"ArgsMeta) Validate(formats", res)
   438  						assertInCode(t, "m.validateArgs(formats", res)
   439  						assertInCode(t, "err := validate.MinLength(\"args\"+\".\"+\"meta\"+\".\"+\"first\",", res)
   440  						assertInCode(t, "err := validate.MaxLength(\"args\"+\".\"+\"meta\"+\".\"+\"first\",", res)
   441  						assertInCode(t, "err := validate.Pattern(\"args\"+\".\"+\"meta\"+\".\"+\"first\",", res)
   442  						assertInCode(t, "err := validate.Minimum(\"args\"+\".\"+\"meta\"+\".\"+\"second\",", res)
   443  						assertInCode(t, "err := validate.Maximum(\"args\"+\".\"+\"meta\"+\".\"+\"second\",", res)
   444  						assertInCode(t, "err := validate.MultipleOf(\"args\"+\".\"+\"meta\"+\".\"+\"second\",", res)
   445  						assertInCode(t, "iThirdSize := int64(len(m.Third))", res)
   446  						assertInCode(t, "err := validate.MinItems(\"args\"+\".\"+\"meta\"+\".\"+\"third\",", res)
   447  						assertInCode(t, "err := validate.MaxItems(\"args\"+\".\"+\"meta\"+\".\"+\"third\",", res)
   448  						assertInCode(t, "err := validate.Minimum(\"args\"+\".\"+\"meta\"+\".\"+\"third\"+\".\"+strconv.Itoa(i),", res)
   449  						assertInCode(t, "err := validate.Maximum(\"args\"+\".\"+\"meta\"+\".\"+\"third\"+\".\"+strconv.Itoa(i),", res)
   450  						assertInCode(t, "err := validate.MultipleOf(\"args\"+\".\"+\"meta\"+\".\"+\"third\"+\".\"+strconv.Itoa(i),", res)
   451  						assertInCode(t, "iFourthSize := int64(len(m.Fourth))", res)
   452  						assertInCode(t, "iiFourthSize := int64(len(m.Fourth[i]))", res)
   453  						assertInCode(t, "iiiFourthSize := int64(len(m.Fourth[i][ii]))", res)
   454  						assertInCode(t, "err := validate.MinItems(\"args\"+\".\"+\"meta\"+\".\"+\"fourth\"+\".\"+strconv.Itoa(i),", res)
   455  						assertInCode(t, "err := validate.MaxItems(\"args\"+\".\"+\"meta\"+\".\"+\"fourth\"+\".\"+strconv.Itoa(i),", res)
   456  						assertInCode(t, "err := validate.MinItems(\"args\"+\".\"+\"meta\"+\".\"+\"fourth\"+\".\"+strconv.Itoa(i)+\".\"+strconv.Itoa(ii),", res)
   457  						assertInCode(t, "err := validate.MaxItems(\"args\"+\".\"+\"meta\"+\".\"+\"fourth\"+\".\"+strconv.Itoa(i)+\".\"+strconv.Itoa(ii),", res)
   458  						assertInCode(t, "err := validate.Minimum(\"args\"+\".\"+\"meta\"+\".\"+\"fourth\"+\".\"+strconv.Itoa(i)+\".\"+strconv.Itoa(ii)+\".\"+strconv.Itoa(iii),", res)
   459  						assertInCode(t, "err := validate.Maximum(\"args\"+\".\"+\"meta\"+\".\"+\"fourth\"+\".\"+strconv.Itoa(i)+\".\"+strconv.Itoa(ii)+\".\"+strconv.Itoa(iii),", res)
   460  						assertInCode(t, "err := validate.MultipleOf(\"args\"+\".\"+\"meta\"+\".\"+\"fourth\"+\".\"+strconv.Itoa(i)+\".\"+strconv.Itoa(ii)+\".\"+strconv.Itoa(iii),", res)
   461  						assertInCode(t, "errors.CompositeValidationError(res...)", res)
   462  					}
   463  				}
   464  			}
   465  		}
   466  	}
   467  }
   468  
   469  func TestSchemaValidation_NamedArrayMulti(t *testing.T) {
   470  	specDoc, err := loads.Spec("../fixtures/codegen/todolist.schemavalidation.yml")
   471  	if assert.NoError(t, err) {
   472  		k := "NamedArrayMulti"
   473  		schema := specDoc.Spec().Definitions[k]
   474  
   475  		opts := opts()
   476  		gm, err := makeGenDefinition(k, "models", schema, specDoc, opts)
   477  		if assert.NoError(t, err) {
   478  			if assertValidation(t, "", "m", gm.GenSchema) {
   479  				buf := bytes.NewBuffer(nil)
   480  				err := templates.MustGet("model").Execute(buf, gm)
   481  				if assert.NoError(t, err) {
   482  					formatted, err := opts.LanguageOpts.FormatContent("named_array_multi.go", buf.Bytes())
   483  					if assert.NoError(t, err) {
   484  						res := string(formatted)
   485  						assertInCode(t, k+") Validate(formats", res)
   486  						assertInCode(t, k+") validateP0(formats", res)
   487  						assertInCode(t, k+") validateP1(formats", res)
   488  						assertInCode(t, "err := validate.Required(\"0\",", res)
   489  						assertInCode(t, "err := validate.MinLength(\"0\",", res)
   490  						assertInCode(t, "err := validate.MaxLength(\"0\",", res)
   491  						assertInCode(t, "err := validate.Pattern(\"0\",", res)
   492  						assertInCode(t, "err := validate.Required(\"1\",", res)
   493  						assertInCode(t, "err := validate.Minimum(\"1\",", res)
   494  						assertInCode(t, "err := validate.Maximum(\"1\",", res)
   495  						assertInCode(t, "err := validate.MultipleOf(\"1\",", res)
   496  						assertInCode(t, "errors.CompositeValidationError(res...)", res)
   497  					}
   498  				}
   499  			}
   500  		}
   501  	}
   502  }
   503  
   504  func TestSchemaValidation_ArrayMultiProps(t *testing.T) {
   505  	specDoc, err := loads.Spec("../fixtures/codegen/todolist.schemavalidation.yml")
   506  	if assert.NoError(t, err) {
   507  		k := "ArrayMultiValidations"
   508  		schema := specDoc.Spec().Definitions[k]
   509  
   510  		opts := opts()
   511  		gm, err := makeGenDefinition(k, "models", schema, specDoc, opts)
   512  		if assert.NoError(t, err) {
   513  			prop := gm.Properties[0]
   514  			if assertValidation(t, "\"args\"", "m.Args", prop) {
   515  				buf := bytes.NewBuffer(nil)
   516  				err := templates.MustGet("model").Execute(buf, gm)
   517  				if assert.NoError(t, err) {
   518  					formatted, err := opts.LanguageOpts.FormatContent("array_multi_validations.go", buf.Bytes())
   519  					if assert.NoError(t, err) {
   520  						res := string(formatted)
   521  						assertInCode(t, k+") Validate(formats", res)
   522  						assertInCode(t, "m.validateArgs(formats", res)
   523  						assertInCode(t, "err := validate.Required(\"P0\",", res)
   524  						assertInCode(t, "err := validate.MinLength(\"P0\",", res)
   525  						assertInCode(t, "err := validate.MaxLength(\"P0\",", res)
   526  						assertInCode(t, "err := validate.Pattern(\"P0\",", res)
   527  						assertInCode(t, "err := validate.Required(\"P1\",", res)
   528  						assertInCode(t, "err := validate.Minimum(\"P1\",", res)
   529  						assertInCode(t, "err := validate.Maximum(\"P1\",", res)
   530  						assertInCode(t, "err := validate.MultipleOf(\"P1\",", res)
   531  						assertInCode(t, "errors.CompositeValidationError(res...)", res)
   532  					}
   533  				}
   534  			}
   535  		}
   536  	}
   537  }
   538  
   539  func TestSchemaValidation_NamedArrayAdditional(t *testing.T) {
   540  	specDoc, err := loads.Spec("../fixtures/codegen/todolist.schemavalidation.yml")
   541  	if assert.NoError(t, err) {
   542  		k := "NamedArrayAdditional"
   543  		schema := specDoc.Spec().Definitions[k]
   544  
   545  		opts := opts()
   546  		gm, err := makeGenDefinition(k, "models", schema, specDoc, opts)
   547  		if assert.NoError(t, err) {
   548  			if assertValidation(t, "", "m", gm.GenSchema) {
   549  				buf := bytes.NewBuffer(nil)
   550  				err := templates.MustGet("model").Execute(buf, gm)
   551  				if assert.NoError(t, err) {
   552  					formatted, err := opts.LanguageOpts.FormatContent("named_array_additional.go", buf.Bytes())
   553  					if assert.NoError(t, err) {
   554  						res := string(formatted)
   555  						assertInCode(t, k+") Validate(formats", res)
   556  						assertInCode(t, k+") validateP0(formats", res)
   557  						assertInCode(t, k+") validateP1(formats", res)
   558  						assertInCode(t, "err := validate.Required(\"0\",", res)
   559  						assertInCode(t, "err := validate.MinLength(\"0\",", res)
   560  						assertInCode(t, "err := validate.MaxLength(\"0\",", res)
   561  						assertInCode(t, "err := validate.Pattern(\"0\",", res)
   562  						assertInCode(t, "err := validate.Required(\"1\",", res)
   563  						assertInCode(t, "err := validate.Minimum(\"1\",", res)
   564  						assertInCode(t, "err := validate.Maximum(\"1\",", res)
   565  						assertInCode(t, "err := validate.MultipleOf(\"1\",", res)
   566  						assertInCode(t, "errors.CompositeValidationError(res...)", res)
   567  						assertInCode(t, "m.NamedArrayAdditionalItems[i]", res)
   568  
   569  					}
   570  				}
   571  			}
   572  		}
   573  	}
   574  }
   575  
   576  func TestSchemaValidation_ArrayAdditionalProps(t *testing.T) {
   577  	specDoc, err := loads.Spec("../fixtures/codegen/todolist.schemavalidation.yml")
   578  	if assert.NoError(t, err) {
   579  		k := "ArrayAdditionalValidations"
   580  		schema := specDoc.Spec().Definitions[k]
   581  
   582  		opts := opts()
   583  		gm, err := makeGenDefinition(k, "models", schema, specDoc, opts)
   584  		if assert.NoError(t, err) {
   585  			prop := gm.Properties[0]
   586  			if assertValidation(t, "\"args\"", "m.Args", prop) {
   587  				buf := bytes.NewBuffer(nil)
   588  				err := templates.MustGet("model").Execute(buf, gm)
   589  				if assert.NoError(t, err) {
   590  					formatted, err := opts.LanguageOpts.FormatContent("array_additional_validations.go", buf.Bytes())
   591  					if assert.NoError(t, err) {
   592  						res := string(formatted)
   593  						assertInCode(t, k+") Validate(formats", res)
   594  						assertInCode(t, "m.validateArgs(formats", res)
   595  						assertInCode(t, "err := validate.Required(\"P0\",", res)
   596  						assertInCode(t, "err := validate.MinLength(\"P0\",", res)
   597  						assertInCode(t, "err := validate.MaxLength(\"P0\",", res)
   598  						assertInCode(t, "err := validate.Pattern(\"P0\",", res)
   599  						assertInCode(t, "err := validate.Required(\"P1\",", res)
   600  						assertInCode(t, "err := validate.Minimum(\"P1\",", res)
   601  						assertInCode(t, "err := validate.Maximum(\"P1\",", res)
   602  						assertInCode(t, "err := validate.MultipleOf(\"P1\",", res)
   603  						assertInCode(t, "errors.CompositeValidationError(res...)", res)
   604  						assertInCode(t, "m.ArrayAdditionalValidationsArgsTuple0Items[i]", res)
   605  					}
   606  				}
   607  			}
   608  		}
   609  	}
   610  }
   611  
   612  func TestSchemaValidation_NamedMap(t *testing.T) {
   613  	specDoc, err := loads.Spec("../fixtures/codegen/todolist.schemavalidation.yml")
   614  	if assert.NoError(t, err) {
   615  		k := "NamedMap"
   616  		schema := specDoc.Spec().Definitions[k]
   617  
   618  		opts := opts()
   619  		gm, err := makeGenDefinition(k, "models", schema, specDoc, opts)
   620  		if assert.NoError(t, err) {
   621  			if assertValidation(t, "", "m", gm.GenSchema) {
   622  				buf := bytes.NewBuffer(nil)
   623  				err := templates.MustGet("model").Execute(buf, gm)
   624  				if assert.NoError(t, err) {
   625  					formatted, err := opts.LanguageOpts.FormatContent("named_map.go", buf.Bytes())
   626  					if assert.NoError(t, err) {
   627  						res := string(formatted)
   628  						assertInCode(t, k+") Validate(formats", res)
   629  						assertInCode(t, "for k := range m {", res)
   630  						assertInCode(t, "err := validate.MinimumInt(k,", res)
   631  						assertInCode(t, "err := validate.MaximumInt(k,", res)
   632  						assertInCode(t, "err := validate.MultipleOf(k,", res)
   633  						assertInCode(t, "errors.CompositeValidationError(res...)", res)
   634  					}
   635  				}
   636  			}
   637  		}
   638  	}
   639  }
   640  
   641  func TestSchemaValidation_MapProps(t *testing.T) {
   642  	specDoc, err := loads.Spec("../fixtures/codegen/todolist.schemavalidation.yml")
   643  	if assert.NoError(t, err) {
   644  		k := "MapValidations"
   645  		schema := specDoc.Spec().Definitions[k]
   646  
   647  		opts := opts()
   648  		gm, err := makeGenDefinition(k, "models", schema, specDoc, opts)
   649  		if assert.NoError(t, err) {
   650  			prop := gm.Properties[0]
   651  			if assertValidation(t, "\"meta\"", "m.Meta", prop) {
   652  				buf := bytes.NewBuffer(nil)
   653  				err := templates.MustGet("model").Execute(buf, gm)
   654  				if assert.NoError(t, err) {
   655  					formatted, err := opts.LanguageOpts.FormatContent("map_validations.go", buf.Bytes())
   656  					if assert.NoError(t, err) {
   657  						res := string(formatted)
   658  						assertInCode(t, k+") Validate(formats", res)
   659  						assertInCode(t, "m.validateMeta(formats", res)
   660  						assertInCode(t, "for k := range m.Meta {", res)
   661  						assertInCode(t, "err := validate.MinimumInt(\"meta\"+\".\"+k,", res)
   662  						assertInCode(t, "err := validate.MaximumInt(\"meta\"+\".\"+k,", res)
   663  						assertInCode(t, "err := validate.MultipleOf(\"meta\"+\".\"+k,", res)
   664  						assertInCode(t, "errors.CompositeValidationError(res...)", res)
   665  					}
   666  				}
   667  			}
   668  		}
   669  	}
   670  }
   671  
   672  func TestSchemaValidation_NamedMapComplex(t *testing.T) {
   673  	specDoc, err := loads.Spec("../fixtures/codegen/todolist.schemavalidation.yml")
   674  	if assert.NoError(t, err) {
   675  		k := "NamedMapComplex"
   676  		schema := specDoc.Spec().Definitions[k]
   677  
   678  		opts := opts()
   679  		gm, err := makeGenDefinition(k, "models", schema, specDoc, opts)
   680  		if assert.NoError(t, err) {
   681  			if assertValidation(t, "", "m", gm.GenSchema) {
   682  				buf := bytes.NewBuffer(nil)
   683  				err := templates.MustGet("model").Execute(buf, gm)
   684  				if assert.NoError(t, err) {
   685  					formatted, err := opts.LanguageOpts.FormatContent("named_map_complex.go", buf.Bytes())
   686  					if assert.NoError(t, err) {
   687  						res := string(formatted)
   688  						assertInCode(t, k+") Validate(formats", res)
   689  						assertInCode(t, "for k := range m {", res)
   690  						assertInCode(t, "val.Validate(formats)", res)
   691  						assertInCode(t, "err := validate.MinLength(\"name\",", res)
   692  						assertInCode(t, "err := validate.MaxLength(\"name\",", res)
   693  						assertInCode(t, "err := validate.Pattern(\"name\",", res)
   694  						assertInCode(t, "err := validate.MinimumInt(\"age\",", res)
   695  						assertInCode(t, "err := validate.MaximumInt(\"age\",", res)
   696  						assertInCode(t, "err := validate.MultipleOf(\"age\",", res)
   697  						assertInCode(t, "errors.CompositeValidationError(res...)", res)
   698  					}
   699  				}
   700  			}
   701  		}
   702  	}
   703  }
   704  
   705  func TestSchemaValidation_MapComplexProps(t *testing.T) {
   706  	specDoc, err := loads.Spec("../fixtures/codegen/todolist.schemavalidation.yml")
   707  	if assert.NoError(t, err) {
   708  		k := "MapComplexValidations"
   709  		schema := specDoc.Spec().Definitions[k]
   710  		opts := opts()
   711  		gm, err := makeGenDefinition(k, "models", schema, specDoc, opts)
   712  		if assert.NoError(t, err) {
   713  			prop := gm.Properties[0]
   714  			if assertValidation(t, "\"meta\"", "m.Meta", prop) {
   715  				buf := bytes.NewBuffer(nil)
   716  				err := templates.MustGet("model").Execute(buf, gm)
   717  				if assert.NoError(t, err) {
   718  					formatted, err := opts.LanguageOpts.FormatContent("map_complex_validations.go", buf.Bytes())
   719  					if assert.NoError(t, err) {
   720  						res := string(formatted)
   721  						assertInCode(t, k+") Validate(formats", res)
   722  						assertInCode(t, "for k := range m.Meta {", res)
   723  						assertInCode(t, "val.Validate(formats)", res)
   724  						assertInCode(t, "err := validate.MinLength(\"name\",", res)
   725  						assertInCode(t, "err := validate.MaxLength(\"name\",", res)
   726  						assertInCode(t, "err := validate.Pattern(\"name\",", res)
   727  						assertInCode(t, "err := validate.MinimumInt(\"age\",", res)
   728  						assertInCode(t, "err := validate.MaximumInt(\"age\",", res)
   729  						assertInCode(t, "err := validate.MultipleOf(\"age\",", res)
   730  						assertInCode(t, "errors.CompositeValidationError(res...)", res)
   731  					}
   732  				}
   733  			}
   734  		}
   735  	}
   736  }
   737  
   738  func TestSchemaValidation_NamedNestedMap(t *testing.T) {
   739  	specDoc, err := loads.Spec("../fixtures/codegen/todolist.schemavalidation.yml")
   740  	if assert.NoError(t, err) {
   741  		k := "NamedNestedMap"
   742  		schema := specDoc.Spec().Definitions[k]
   743  
   744  		opts := opts()
   745  		gm, err := makeGenDefinition(k, "models", schema, specDoc, opts)
   746  		if assert.NoError(t, err) {
   747  			if assertValidation(t, "", "m", gm.GenSchema) {
   748  				buf := bytes.NewBuffer(nil)
   749  				err := templates.MustGet("model").Execute(buf, gm)
   750  				if assert.NoError(t, err) {
   751  					formatted, err := opts.LanguageOpts.FormatContent("named_nested_map.go", buf.Bytes())
   752  					if assert.NoError(t, err) {
   753  						res := string(formatted)
   754  						assertInCode(t, k+") Validate(formats", res)
   755  						assertInCode(t, "for k := range m {", res)
   756  						assertInCode(t, "for kk := range m[k] {", res)
   757  						assertInCode(t, "for kkk := range m[k][kk] {", res)
   758  						assertInCode(t, "err := validate.MinimumInt(k+\".\"+kk+\".\"+kkk,", res)
   759  						assertInCode(t, "err := validate.MaximumInt(k+\".\"+kk+\".\"+kkk,", res)
   760  						assertInCode(t, "err := validate.MultipleOf(k+\".\"+kk+\".\"+kkk,", res)
   761  						assertInCode(t, "errors.CompositeValidationError(res...)", res)
   762  					}
   763  				}
   764  			}
   765  		}
   766  	}
   767  }
   768  
   769  func TestSchemaValidation_NestedMapProps(t *testing.T) {
   770  	specDoc, err := loads.Spec("../fixtures/codegen/todolist.schemavalidation.yml")
   771  	if assert.NoError(t, err) {
   772  		k := "NestedMapValidations"
   773  		schema := specDoc.Spec().Definitions[k]
   774  
   775  		opts := opts()
   776  		gm, err := makeGenDefinition(k, "models", schema, specDoc, opts)
   777  		if assert.NoError(t, err) {
   778  			prop := gm.Properties[0]
   779  			if assertValidation(t, "\"meta\"", "m.Meta", prop) {
   780  				buf := bytes.NewBuffer(nil)
   781  				err := templates.MustGet("model").Execute(buf, gm)
   782  				if assert.NoError(t, err) {
   783  					formatted, err := opts.LanguageOpts.FormatContent("nested_map_validations.go", buf.Bytes())
   784  					if assert.NoError(t, err) {
   785  						res := string(formatted)
   786  						assertInCode(t, k+") Validate(formats", res)
   787  						assertInCode(t, "m.validateMeta(formats", res)
   788  						assertInCode(t, "for k := range m.Meta {", res)
   789  						assertInCode(t, "for kk := range m.Meta[k] {", res)
   790  						assertInCode(t, "for kkk := range m.Meta[k][kk] {", res)
   791  						assertInCode(t, "err := validate.MinimumInt(\"meta\"+\".\"+k+\".\"+kk+\".\"+kkk,", res)
   792  						assertInCode(t, "err := validate.MaximumInt(\"meta\"+\".\"+k+\".\"+kk+\".\"+kkk,", res)
   793  						assertInCode(t, "err := validate.MultipleOf(\"meta\"+\".\"+k+\".\"+kk+\".\"+kkk,", res)
   794  						assertInCode(t, "errors.CompositeValidationError(res...)", res)
   795  					}
   796  				}
   797  			}
   798  		}
   799  	}
   800  }
   801  func TestAdditionalProperties_Simple(t *testing.T) {
   802  	specDoc, err := loads.Spec("../fixtures/codegen/todolist.schemavalidation.yml")
   803  	if assert.NoError(t, err) {
   804  		k := "NamedMapComplex"
   805  		schema := specDoc.Spec().Definitions[k]
   806  		tr := &typeResolver{
   807  			ModelsPackage: "",
   808  			ModelName:     k,
   809  			Doc:           specDoc,
   810  		}
   811  
   812  		sg := schemaGenContext{
   813  			Path:         "",
   814  			Name:         k,
   815  			Receiver:     "m",
   816  			IndexVar:     "i",
   817  			ValueExpr:    "m",
   818  			Schema:       schema,
   819  			Required:     false,
   820  			TypeResolver: tr,
   821  			Named:        true,
   822  			ExtraSchemas: make(map[string]GenSchema),
   823  		}
   824  
   825  		fsm, lsm, err := newMapStack(&sg)
   826  		if assert.NoError(t, err) {
   827  			assert.NotNil(t, fsm.Type)
   828  			assert.Equal(t, &schema, fsm.Type)
   829  			assert.Equal(t, fsm, lsm)
   830  			assert.NotNil(t, fsm.Type.AdditionalProperties)
   831  			assert.NotNil(t, fsm.Type.AdditionalProperties.Schema)
   832  			assert.NotNil(t, fsm.NewObj)
   833  			assert.Nil(t, fsm.Next)
   834  			assert.Equal(t, "#/definitions/NamedMapComplexAnon", fsm.Type.AdditionalProperties.Schema.Ref.GetURL().String())
   835  
   836  			assert.NoError(t, lsm.Build())
   837  		}
   838  	}
   839  }
   840  
   841  func TestAdditionalProperties_Nested(t *testing.T) {
   842  	specDoc, err := loads.Spec("../fixtures/codegen/todolist.schemavalidation.yml")
   843  	if assert.NoError(t, err) {
   844  		k := "NamedNestedMapComplex"
   845  		schema := specDoc.Spec().Definitions[k]
   846  		tr := &typeResolver{
   847  			ModelsPackage: "",
   848  			ModelName:     k,
   849  			Doc:           specDoc,
   850  		}
   851  
   852  		sg := schemaGenContext{
   853  			Path:         "",
   854  			Name:         k,
   855  			Receiver:     "m",
   856  			IndexVar:     "i",
   857  			ValueExpr:    "m",
   858  			Schema:       schema,
   859  			Required:     false,
   860  			TypeResolver: tr,
   861  			Named:        true,
   862  			ExtraSchemas: make(map[string]GenSchema),
   863  		}
   864  
   865  		fsm, lsm, err := newMapStack(&sg)
   866  		if assert.NoError(t, err) {
   867  			assert.NotNil(t, fsm.Type)
   868  			assert.Equal(t, &schema, fsm.Type)
   869  			assert.Equal(t, "", fsm.Context.Path)
   870  
   871  			assert.NotNil(t, schema.AdditionalProperties.Schema)
   872  			if assert.NotNil(t, fsm.Next) && assert.Nil(t, fsm.Previous) {
   873  				assert.NotNil(t, fsm.Type)
   874  				assert.Equal(t, &schema, fsm.Type)
   875  				assert.NotEqual(t, fsm, lsm)
   876  				assert.NotNil(t, fsm.Type.AdditionalProperties)
   877  				assert.NotNil(t, fsm.Type.AdditionalProperties.Schema)
   878  				assert.Nil(t, fsm.NewObj)
   879  				assert.Nil(t, fsm.Next.NewObj)
   880  				assert.NotNil(t, fsm.Next.Previous)
   881  				assert.NotNil(t, fsm.Next.Next)
   882  				assert.NotNil(t, fsm.Next.Next.NewObj)
   883  				assert.NotNil(t, fsm.Next.Next.ValueRef)
   884  				assert.Nil(t, fsm.Next.Next.Next)
   885  				assert.Equal(t, fsm.Next.Next, lsm)
   886  				assert.NoError(t, lsm.Build())
   887  			}
   888  		}
   889  	}
   890  }
   891  
   892  func TestSchemaValidation_NamedNestedMapComplex(t *testing.T) {
   893  	specDoc, err := loads.Spec("../fixtures/codegen/todolist.schemavalidation.yml")
   894  	if assert.NoError(t, err) {
   895  		k := "NamedNestedMapComplex"
   896  		schema := specDoc.Spec().Definitions[k]
   897  
   898  		opts := opts()
   899  		gm, err := makeGenDefinition(k, "models", schema, specDoc, opts)
   900  		if assert.NoError(t, err) {
   901  			if assertValidation(t, "", "m", gm.GenSchema) {
   902  				if assert.True(t, gm.GenSchema.AdditionalProperties.HasValidations) {
   903  					if assert.True(t, gm.GenSchema.AdditionalProperties.AdditionalProperties.HasValidations) {
   904  						buf := bytes.NewBuffer(nil)
   905  						err := templates.MustGet("model").Execute(buf, gm)
   906  						if assert.NoError(t, err) {
   907  							formatted, err := opts.LanguageOpts.FormatContent("named_nested_map_complex.go", buf.Bytes())
   908  							if assert.NoError(t, err) {
   909  								res := string(formatted)
   910  								assertInCode(t, k+") Validate(formats", res)
   911  								assertInCode(t, "for k := range m {", res)
   912  								assertInCode(t, "for kk := range m[k] {", res)
   913  								assertInCode(t, "for kkk := range m[k][kk] {", res)
   914  								assertInCode(t, "val.Validate(formats)", res)
   915  								assertInCode(t, "err := validate.MinLength(\"name\",", res)
   916  								assertInCode(t, "err := validate.MaxLength(\"name\",", res)
   917  								assertInCode(t, "err := validate.Pattern(\"name\",", res)
   918  								assertInCode(t, "err := validate.MinimumInt(\"age\",", res)
   919  								assertInCode(t, "err := validate.MaximumInt(\"age\",", res)
   920  								assertInCode(t, "err := validate.MultipleOf(\"age\",", res)
   921  								assertInCode(t, "errors.CompositeValidationError(res...)", res)
   922  							} else {
   923  								fmt.Println(buf.String())
   924  							}
   925  						}
   926  					}
   927  				}
   928  			}
   929  		}
   930  	}
   931  }
   932  
   933  func TestSchemaValidation_NestedMapPropsComplex(t *testing.T) {
   934  	specDoc, err := loads.Spec("../fixtures/codegen/todolist.schemavalidation.yml")
   935  	if assert.NoError(t, err) {
   936  		k := "NestedMapComplexValidations"
   937  		schema := specDoc.Spec().Definitions[k]
   938  
   939  		opts := opts()
   940  		gm, err := makeGenDefinition(k, "models", schema, specDoc, opts)
   941  		if assert.NoError(t, err) {
   942  			prop := gm.Properties[0]
   943  			if assertValidation(t, "\"meta\"", "m.Meta", prop) {
   944  				buf := bytes.NewBuffer(nil)
   945  				err := templates.MustGet("model").Execute(buf, gm)
   946  				if assert.NoError(t, err) {
   947  					formatted, err := opts.LanguageOpts.FormatContent("nested_map_complex_validations.go", buf.Bytes())
   948  					if assert.NoError(t, err) {
   949  						res := string(formatted)
   950  						assertInCode(t, k+") Validate(formats", res)
   951  						assertInCode(t, "m.validateMeta(formats", res)
   952  						assertInCode(t, "for k := range m.Meta {", res)
   953  						assertInCode(t, "for kk := range m.Meta[k] {", res)
   954  						assertInCode(t, "for kkk := range m.Meta[k][kk] {", res)
   955  						assertInCode(t, "val.Validate(formats)", res)
   956  						assertInCode(t, "err := validate.MinLength(\"name\",", res)
   957  						assertInCode(t, "err := validate.MaxLength(\"name\",", res)
   958  						assertInCode(t, "err := validate.Pattern(\"name\",", res)
   959  						assertInCode(t, "err := validate.MinimumInt(\"age\",", res)
   960  						assertInCode(t, "err := validate.MaximumInt(\"age\",", res)
   961  						assertInCode(t, "err := validate.MultipleOf(\"age\",", res)
   962  						assertInCode(t, "errors.CompositeValidationError(res...)", res)
   963  					}
   964  				}
   965  			}
   966  		}
   967  	}
   968  }
   969  
   970  func TestSchemaValidation_NamedAllOf(t *testing.T) {
   971  	specDoc, err := loads.Spec("../fixtures/codegen/todolist.schemavalidation.yml")
   972  	if assert.NoError(t, err) {
   973  		k := "NamedAllOf"
   974  		schema := specDoc.Spec().Definitions[k]
   975  
   976  		opts := opts()
   977  		gm, err := makeGenDefinition(k, "models", schema, specDoc, opts)
   978  		if assert.NoError(t, err) {
   979  			if assertValidation(t, "", "m", gm.GenSchema) {
   980  				buf := bytes.NewBuffer(nil)
   981  				err := templates.MustGet("model").Execute(buf, gm)
   982  				if assert.NoError(t, err) {
   983  					formatted, err := opts.LanguageOpts.FormatContent("named_all_of.go", buf.Bytes())
   984  					if assert.NoError(t, err) {
   985  						res := string(formatted)
   986  						assertInCode(t, k+") Validate(formats", res)
   987  						assertInCode(t, k+") validateName(formats", res)
   988  						assertInCode(t, k+") validateAge(formats", res)
   989  						assertInCode(t, k+") validateArgs(formats", res)
   990  						assertInCode(t, k+") validateAssoc(formats", res)
   991  						assertInCode(t, k+") validateOpts(formats", res)
   992  						assertInCode(t, k+") validateExtOpts(formats", res)
   993  						assertInCode(t, k+") validateCoords(formats", res)
   994  						assertInCode(t, "validate.MinLength(\"name\",", res)
   995  						assertInCode(t, "validate.MinimumInt(\"age\",", res)
   996  						assertInCode(t, "validate.MinItems(\"args\",", res)
   997  						assertInCode(t, "validate.MinItems(\"assoc\",", res)
   998  						assertInCode(t, "validate.MinItems(\"assoc\"+\".\"+strconv.Itoa(i),", res)
   999  						assertInCode(t, "validate.MinItems(\"assoc\"+\".\"+strconv.Itoa(i)+\".\"+strconv.Itoa(ii),", res)
  1000  						assertInCode(t, "validate.MinLength(\"assoc\"+\".\"+strconv.Itoa(i)+\".\"+strconv.Itoa(ii)+\".\"+strconv.Itoa(iii),", res)
  1001  						assertInCode(t, "validate.Minimum(\"opts\"+\".\"+k,", res)
  1002  						assertInCode(t, "validate.MinimumInt(\"extOpts\"+\".\"+k+\".\"+kk+\".\"+kkk,", res)
  1003  						assertInCode(t, "validate.MinLength(\"coords\"+\".\"+\"name\",", res)
  1004  						assertInCode(t, "errors.CompositeValidationError(res...)", res)
  1005  					}
  1006  				}
  1007  			}
  1008  		}
  1009  	}
  1010  }
  1011  
  1012  func TestSchemaValidation_AllOfProps(t *testing.T) {
  1013  	specDoc, err := loads.Spec("../fixtures/codegen/todolist.schemavalidation.yml")
  1014  	if assert.NoError(t, err) {
  1015  		k := "AllOfValidations"
  1016  		schema := specDoc.Spec().Definitions[k]
  1017  
  1018  		opts := opts()
  1019  		gm, err := makeGenDefinition(k, "models", schema, specDoc, opts)
  1020  		if assert.NoError(t, err) {
  1021  			prop := gm.Properties[0]
  1022  			if assertValidation(t, "\"meta\"", "m.Meta", prop) {
  1023  				buf := bytes.NewBuffer(nil)
  1024  				err := templates.MustGet("model").Execute(buf, gm)
  1025  				if assert.NoError(t, err) {
  1026  					formatted, err := opts.LanguageOpts.FormatContent("all_of_validations.go", buf.Bytes())
  1027  					if assert.NoError(t, err) {
  1028  						res := string(formatted)
  1029  						assertInCode(t, k+") Validate(formats", res)
  1030  						assertInCode(t, "m.validateMeta(formats", res)
  1031  						assertInCode(t, "validate.MinLength(\"meta\"+\".\"+\"name\",", res)
  1032  						assertInCode(t, "validate.MinimumInt(\"meta\"+\".\"+\"age\",", res)
  1033  						assertInCode(t, "validate.MinItems(\"meta\"+\".\"+\"args\",", res)
  1034  						assertInCode(t, "validate.MinItems(\"meta\"+\".\"+\"assoc\",", res)
  1035  						assertInCode(t, "validate.MinItems(\"meta\"+\".\"+\"assoc\"+\".\"+strconv.Itoa(i),", res)
  1036  						assertInCode(t, "validate.MinItems(\"meta\"+\".\"+\"assoc\"+\".\"+strconv.Itoa(i)+\".\"+strconv.Itoa(ii),", res)
  1037  						assertInCode(t, "validate.MinLength(\"meta\"+\".\"+\"assoc\"+\".\"+strconv.Itoa(i)+\".\"+strconv.Itoa(ii)+\".\"+strconv.Itoa(iii),", res)
  1038  						assertInCode(t, "validate.MinimumInt(\"meta\"+\".\"+\"opts\"+\".\"+k,", res)
  1039  						assertInCode(t, "validate.MinimumInt(\"meta\"+\".\"+\"extOpts\"+\".\"+k+\".\"+kk+\".\"+kkk,", res)
  1040  						assertInCode(t, "validate.MinLength(\"meta\"+\".\"+\"coords\"+\".\"+\"name\",", res)
  1041  						assertInCode(t, "errors.CompositeValidationError(res...)", res)
  1042  					}
  1043  				}
  1044  			}
  1045  		}
  1046  	}
  1047  }
  1048  
  1049  func TestSchemaValidation_RefedAllOf(t *testing.T) {
  1050  	specDoc, err := loads.Spec("../fixtures/codegen/todolist.schemavalidation.yml")
  1051  	if assert.NoError(t, err) {
  1052  		k := "RefedAllOfValidations"
  1053  		schema := specDoc.Spec().Definitions[k]
  1054  
  1055  		opts := opts()
  1056  		gm, err := makeGenDefinition(k, "models", schema, specDoc, opts)
  1057  		if assert.NoError(t, err) && assert.Len(t, gm.AllOf, 2) {
  1058  			//prop := gm.AllOf[0]
  1059  			//if assertValidation(t, "\"meta\"", "m.Meta", prop) {
  1060  			buf := bytes.NewBuffer(nil)
  1061  			err := templates.MustGet("model").Execute(buf, gm)
  1062  			if assert.NoError(t, err) {
  1063  				formatted, err := opts.LanguageOpts.FormatContent("all_of_validations.go", buf.Bytes())
  1064  				if assert.NoError(t, err) {
  1065  					res := string(formatted)
  1066  					assertInCode(t, k+") Validate(formats", res)
  1067  					assertInCode(t, "m.NamedString.Validate(formats)", res)
  1068  					assertInCode(t, "m.NamedNumber.Validate(formats)", res)
  1069  					assertInCode(t, "errors.CompositeValidationError(res...)", res)
  1070  				}
  1071  			}
  1072  			//}
  1073  		}
  1074  	}
  1075  }
  1076  
  1077  func TestSchemaValidation_SimpleZeroAllowed(t *testing.T) {
  1078  
  1079  	specDoc, err := loads.Spec("../fixtures/codegen/todolist.schemavalidation.yml")
  1080  	if assert.NoError(t, err) {
  1081  		k := "SimpleZeroAllowed"
  1082  		schema := specDoc.Spec().Definitions[k]
  1083  
  1084  		opts := opts()
  1085  		gm, err := makeGenDefinition(k, "models", schema, specDoc, opts)
  1086  		if assert.NoError(t, err) {
  1087  			buf := bytes.NewBuffer(nil)
  1088  			err := templates.MustGet("model").Execute(buf, gm)
  1089  			if assert.NoError(t, err) {
  1090  				formatted, err := opts.LanguageOpts.FormatContent("simple_zero_allowed.go", buf.Bytes())
  1091  				if assert.NoError(t, err) {
  1092  					res := string(formatted)
  1093  					assertInCode(t, k+") Validate(formats", res)
  1094  					assertInCode(t, "swag.IsZero(m.ID)", res)
  1095  					assertInCode(t, "validate.Required(\"name\", \"body\", m.Name)", res)
  1096  					assertInCode(t, "validate.MinLength(\"id\", \"body\", string(m.ID), 2)", res)
  1097  					assertInCode(t, "validate.Required(\"urls\", \"body\", m.Urls)", res)
  1098  					assertInCode(t, "errors.CompositeValidationError(res...)", res)
  1099  				}
  1100  			}
  1101  		}
  1102  	}
  1103  }
  1104  
  1105  func TestSchemaValidation_Pet(t *testing.T) {
  1106  	specDoc, err := loads.Spec("../fixtures/codegen/todolist.schemavalidation.yml")
  1107  	if assert.NoError(t, err) {
  1108  		k := "Pet"
  1109  		schema := specDoc.Spec().Definitions[k]
  1110  
  1111  		opts := opts()
  1112  		gm, err := makeGenDefinition(k, "models", schema, specDoc, opts)
  1113  		if assert.NoError(t, err) {
  1114  			buf := bytes.NewBuffer(nil)
  1115  			err := templates.MustGet("model").Execute(buf, gm)
  1116  			if assert.NoError(t, err) {
  1117  				formatted, err := opts.LanguageOpts.FormatContent("pet.go", buf.Bytes())
  1118  				if assert.NoError(t, err) {
  1119  					res := string(formatted)
  1120  					assertInCode(t, k+") Validate(formats", res)
  1121  					assertInCode(t, "swag.IsZero(m.Status)", res)
  1122  					assertInCode(t, "swag.IsZero(m.Tags)", res)
  1123  					assertInCode(t, "validate.Required(\"name\", \"body\", m.Name)", res)
  1124  					assertInCode(t, "validate.Required(\"photoUrls\", \"body\", m.PhotoUrls)", res)
  1125  					assertInCode(t, "errors.CompositeValidationError(res...)", res)
  1126  				}
  1127  			}
  1128  		}
  1129  	}
  1130  }
  1131  
  1132  func TestSchemaValidation_UpdateOrg(t *testing.T) {
  1133  	specDoc, err := loads.Spec("../fixtures/codegen/todolist.schemavalidation.yml")
  1134  	if assert.NoError(t, err) {
  1135  		k := "UpdateOrg"
  1136  		schema := specDoc.Spec().Definitions[k]
  1137  
  1138  		opts := opts()
  1139  		gm, err := makeGenDefinition(k, "models", schema, specDoc, opts)
  1140  		if assert.NoError(t, err) {
  1141  			buf := bytes.NewBuffer(nil)
  1142  			err := templates.MustGet("model").Execute(buf, gm)
  1143  			if assert.NoError(t, err) {
  1144  				formatted, err := opts.LanguageOpts.FormatContent("pet.go", buf.Bytes())
  1145  				if assert.NoError(t, err) {
  1146  					res := string(formatted)
  1147  					assertInCode(t, k+") Validate(formats", res)
  1148  					assertInCode(t, "swag.IsZero(m.TagExpiration)", res)
  1149  					assertInCode(t, "validate.MinimumInt(\"tag_expiration\", \"body\", int64(*m.TagExpiration)", res)
  1150  					assertInCode(t, "validate.MaximumInt(\"tag_expiration\", \"body\", int64(*m.TagExpiration)", res)
  1151  					assertInCode(t, "errors.CompositeValidationError(res...)", res)
  1152  				} else {
  1153  					fmt.Println(buf.String())
  1154  				}
  1155  			}
  1156  		}
  1157  	}
  1158  }