github.com/josephspurrier/go-swagger@v0.2.1-0.20221129144919-1f672a142a00/scan/schema_test.go (about)

     1  //go:build !go1.11
     2  // +build !go1.11
     3  
     4  // Copyright 2015 go-swagger maintainers
     5  //
     6  // Licensed under the Apache License, Version 2.0 (the "License");
     7  // you may not use this file except in compliance with the License.
     8  // You may obtain a copy of the License at
     9  //
    10  //    http://www.apache.org/licenses/LICENSE-2.0
    11  //
    12  // Unless required by applicable law or agreed to in writing, software
    13  // distributed under the License is distributed on an "AS IS" BASIS,
    14  // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    15  // See the License for the specific language governing permissions and
    16  // limitations under the License.
    17  
    18  package scan
    19  
    20  import (
    21  	"os"
    22  	"path/filepath"
    23  	"testing"
    24  
    25  	"github.com/go-openapi/spec"
    26  	"github.com/stretchr/testify/assert"
    27  )
    28  
    29  func TestSchemaParser(t *testing.T) {
    30  	_ = classificationProg
    31  	schema := noModelDefs["NoModel"]
    32  
    33  	assert.Equal(t, spec.StringOrArray([]string{"object"}), schema.Type)
    34  	assert.Equal(t, "NoModel is a struct without an annotation.", schema.Title)
    35  	assert.Equal(t, "NoModel exists in a package\nbut is not annotated with the swagger model annotations\nso it should now show up in a test.", schema.Description)
    36  	assert.Len(t, schema.Required, 3)
    37  	assert.Len(t, schema.Properties, 11)
    38  
    39  	assertProperty(t, &schema, "integer", "id", "int64", "ID")
    40  	prop, ok := schema.Properties["id"]
    41  	assert.Equal(t, "ID of this no model instance.\nids in this application start at 11 and are smaller than 1000", prop.Description)
    42  	assert.True(t, ok, "should have had an 'id' property")
    43  	assert.EqualValues(t, 1000, *prop.Maximum)
    44  	assert.True(t, prop.ExclusiveMaximum, "'id' should have had an exclusive maximum")
    45  	assert.NotNil(t, prop.Minimum)
    46  	assert.EqualValues(t, 10, *prop.Minimum)
    47  	assert.True(t, prop.ExclusiveMinimum, "'id' should have had an exclusive minimum")
    48  	assert.Equal(t, 11, prop.Default, "ID default value is incorrect")
    49  
    50  	assertProperty(t, &schema, "string", "NoNameOmitEmpty", "", "")
    51  	prop, ok = schema.Properties["NoNameOmitEmpty"]
    52  	assert.Equal(t, "A field which has omitempty set but no name", prop.Description)
    53  	assert.True(t, ok, "should have had an 'NoNameOmitEmpty' property")
    54  
    55  	assertProperty(t, &schema, "integer", "score", "int32", "Score")
    56  	prop, ok = schema.Properties["score"]
    57  	assert.Equal(t, "The Score of this model", prop.Description)
    58  	assert.True(t, ok, "should have had a 'score' property")
    59  	assert.EqualValues(t, 45, *prop.Maximum)
    60  	assert.False(t, prop.ExclusiveMaximum, "'score' should not have had an exclusive maximum")
    61  	assert.NotNil(t, prop.Minimum)
    62  	assert.EqualValues(t, 3, *prop.Minimum)
    63  	assert.False(t, prop.ExclusiveMinimum, "'score' should not have had an exclusive minimum")
    64  	assert.Equal(t, 27, prop.Example)
    65  
    66  	expectedNameExtensions := spec.Extensions{
    67  		"x-go-name": "Name",
    68  		"x-property-array": []interface{}{
    69  			"value1",
    70  			"value2",
    71  		},
    72  		"x-property-array-obj": []interface{}{
    73  			map[string]interface{}{
    74  				"name":  "obj",
    75  				"value": "field",
    76  			},
    77  		},
    78  		"x-property-value": "value",
    79  	}
    80  
    81  	assertProperty(t, &schema, "string", "name", "", "Name")
    82  	prop, ok = schema.Properties["name"]
    83  	assert.True(t, ok)
    84  	assert.Equal(t, "Name of this no model instance", prop.Description)
    85  	assert.EqualValues(t, 4, *prop.MinLength)
    86  	assert.EqualValues(t, 50, *prop.MaxLength)
    87  	assert.Equal(t, "[A-Za-z0-9-.]*", prop.Pattern)
    88  	assert.EqualValues(t, expectedNameExtensions, prop.Extensions)
    89  
    90  	assertProperty(t, &schema, "string", "created", "date-time", "Created")
    91  	prop, ok = schema.Properties["created"]
    92  	assert.Equal(t, "Created holds the time when this entry was created", prop.Description)
    93  	assert.True(t, ok, "should have a 'created' property")
    94  	assert.True(t, prop.ReadOnly, "'created' should be read only")
    95  
    96  	assertProperty(t, &schema, "string", "gocreated", "date-time", "GoTimeCreated")
    97  	prop, ok = schema.Properties["gocreated"]
    98  	assert.Equal(t, "GoTimeCreated holds the time when this entry was created in go time.Time", prop.Description)
    99  	assert.True(t, ok, "should have a 'gocreated' property")
   100  
   101  	assertArrayProperty(t, &schema, "string", "foo_slice", "", "FooSlice")
   102  	prop, ok = schema.Properties["foo_slice"]
   103  	assert.Equal(t, "a FooSlice has foos which are strings", prop.Description)
   104  	assert.True(t, ok, "should have a 'foo_slice' property")
   105  	assert.NotNil(t, prop.Items, "foo_slice should have had an items property")
   106  	assert.NotNil(t, prop.Items.Schema, "foo_slice.items should have had a schema property")
   107  	assert.True(t, prop.UniqueItems, "'foo_slice' should have unique items")
   108  	assert.EqualValues(t, 3, *prop.MinItems, "'foo_slice' should have had 3 min items")
   109  	assert.EqualValues(t, 10, *prop.MaxItems, "'foo_slice' should have had 10 max items")
   110  	itprop := prop.Items.Schema
   111  	assert.EqualValues(t, 3, *itprop.MinLength, "'foo_slice.items.minLength' should have been 3")
   112  	assert.EqualValues(t, 10, *itprop.MaxLength, "'foo_slice.items.maxLength' should have been 10")
   113  	assert.EqualValues(t, "\\w+", itprop.Pattern, "'foo_slice.items.pattern' should have \\w+")
   114  
   115  	assertArrayProperty(t, &schema, "string", "time_slice", "date-time", "TimeSlice")
   116  	prop, ok = schema.Properties["time_slice"]
   117  	assert.Equal(t, "a TimeSlice is a slice of times", prop.Description)
   118  	assert.True(t, ok, "should have a 'time_slice' property")
   119  	assert.NotNil(t, prop.Items, "time_slice should have had an items property")
   120  	assert.NotNil(t, prop.Items.Schema, "time_slice.items should have had a schema property")
   121  	assert.True(t, prop.UniqueItems, "'time_slice' should have unique items")
   122  	assert.EqualValues(t, 3, *prop.MinItems, "'time_slice' should have had 3 min items")
   123  	assert.EqualValues(t, 10, *prop.MaxItems, "'time_slice' should have had 10 max items")
   124  
   125  	assertArrayProperty(t, &schema, "array", "bar_slice", "", "BarSlice")
   126  	prop, ok = schema.Properties["bar_slice"]
   127  	assert.Equal(t, "a BarSlice has bars which are strings", prop.Description)
   128  	assert.True(t, ok, "should have a 'bar_slice' property")
   129  	assert.NotNil(t, prop.Items, "bar_slice should have had an items property")
   130  	assert.NotNil(t, prop.Items.Schema, "bar_slice.items should have had a schema property")
   131  	assert.True(t, prop.UniqueItems, "'bar_slice' should have unique items")
   132  	assert.EqualValues(t, 3, *prop.MinItems, "'bar_slice' should have had 3 min items")
   133  	assert.EqualValues(t, 10, *prop.MaxItems, "'bar_slice' should have had 10 max items")
   134  	itprop = prop.Items.Schema
   135  	if assert.NotNil(t, itprop) {
   136  		assert.EqualValues(t, 4, *itprop.MinItems, "'bar_slice.items.minItems' should have been 4")
   137  		assert.EqualValues(t, 9, *itprop.MaxItems, "'bar_slice.items.maxItems' should have been 9")
   138  		itprop2 := itprop.Items.Schema
   139  		if assert.NotNil(t, itprop2) {
   140  			assert.EqualValues(t, 5, *itprop2.MinItems, "'bar_slice.items.items.minItems' should have been 5")
   141  			assert.EqualValues(t, 8, *itprop2.MaxItems, "'bar_slice.items.items.maxItems' should have been 8")
   142  			itprop3 := itprop2.Items.Schema
   143  			if assert.NotNil(t, itprop3) {
   144  				assert.EqualValues(t, 3, *itprop3.MinLength, "'bar_slice.items.items.items.minLength' should have been 3")
   145  				assert.EqualValues(t, 10, *itprop3.MaxLength, "'bar_slice.items.items.items.maxLength' should have been 10")
   146  				assert.EqualValues(t, "\\w+", itprop3.Pattern, "'bar_slice.items.items.items.pattern' should have \\w+")
   147  			}
   148  		}
   149  	}
   150  
   151  	assertArrayProperty(t, &schema, "array", "deep_time_slice", "", "DeepTimeSlice")
   152  	prop, ok = schema.Properties["deep_time_slice"]
   153  	assert.Equal(t, "a DeepSlice has bars which are time", prop.Description)
   154  	assert.True(t, ok, "should have a 'deep_time_slice' property")
   155  	assert.NotNil(t, prop.Items, "deep_time_slice should have had an items property")
   156  	assert.NotNil(t, prop.Items.Schema, "deep_time_slice.items should have had a schema property")
   157  	assert.True(t, prop.UniqueItems, "'deep_time_slice' should have unique items")
   158  	assert.EqualValues(t, 3, *prop.MinItems, "'deep_time_slice' should have had 3 min items")
   159  	assert.EqualValues(t, 10, *prop.MaxItems, "'deep_time_slice' should have had 10 max items")
   160  	itprop = prop.Items.Schema
   161  	if assert.NotNil(t, itprop) {
   162  		assert.EqualValues(t, 4, *itprop.MinItems, "'deep_time_slice.items.minItems' should have been 4")
   163  		assert.EqualValues(t, 9, *itprop.MaxItems, "'deep_time_slice.items.maxItems' should have been 9")
   164  		itprop2 := itprop.Items.Schema
   165  		if assert.NotNil(t, itprop2) {
   166  			assert.EqualValues(t, 5, *itprop2.MinItems, "'deep_time_slice.items.items.minItems' should have been 5")
   167  			assert.EqualValues(t, 8, *itprop2.MaxItems, "'deep_time_slice.items.items.maxItems' should have been 8")
   168  			itprop3 := itprop2.Items.Schema
   169  			assert.NotNil(t, itprop3)
   170  		}
   171  	}
   172  
   173  	assertArrayProperty(t, &schema, "object", "items", "", "Items")
   174  	prop, ok = schema.Properties["items"]
   175  	assert.True(t, ok, "should have an 'items' slice")
   176  	assert.NotNil(t, prop.Items, "items should have had an items property")
   177  	assert.NotNil(t, prop.Items.Schema, "items.items should have had a schema property")
   178  	itprop = prop.Items.Schema
   179  	assert.Len(t, itprop.Properties, 5)
   180  	assert.Len(t, itprop.Required, 4)
   181  	assertProperty(t, itprop, "integer", "id", "int32", "ID")
   182  	iprop, ok := itprop.Properties["id"]
   183  	assert.True(t, ok)
   184  	assert.Equal(t, "ID of this no model instance.\nids in this application start at 11 and are smaller than 1000", iprop.Description)
   185  	assert.EqualValues(t, 1000, *iprop.Maximum)
   186  	assert.True(t, iprop.ExclusiveMaximum, "'id' should have had an exclusive maximum")
   187  	assert.NotNil(t, iprop.Minimum)
   188  	assert.EqualValues(t, 10, *iprop.Minimum)
   189  	assert.True(t, iprop.ExclusiveMinimum, "'id' should have had an exclusive minimum")
   190  	assert.Equal(t, 11, iprop.Default, "ID default value is incorrect")
   191  
   192  	assertRef(t, itprop, "pet", "Pet", "#/definitions/pet")
   193  	iprop, ok = itprop.Properties["pet"]
   194  	assert.True(t, ok)
   195  	if itprop.Ref.String() != "" {
   196  		assert.Equal(t, "The Pet to add to this NoModel items bucket.\nPets can appear more than once in the bucket", iprop.Description)
   197  	}
   198  
   199  	assertProperty(t, itprop, "integer", "quantity", "int16", "Quantity")
   200  	iprop, ok = itprop.Properties["quantity"]
   201  	assert.True(t, ok)
   202  	assert.Equal(t, "The amount of pets to add to this bucket.", iprop.Description)
   203  	assert.EqualValues(t, 1, *iprop.Minimum)
   204  	assert.EqualValues(t, 10, *iprop.Maximum)
   205  
   206  	assertProperty(t, itprop, "string", "expiration", "date-time", "Expiration")
   207  	iprop, ok = itprop.Properties["expiration"]
   208  	assert.True(t, ok)
   209  	assert.Equal(t, "A dummy expiration date.", iprop.Description)
   210  
   211  	assertProperty(t, itprop, "string", "notes", "", "Notes")
   212  	iprop, ok = itprop.Properties["notes"]
   213  	assert.True(t, ok)
   214  	assert.Equal(t, "Notes to add to this item.\nThis can be used to add special instructions.", iprop.Description)
   215  
   216  	definitions := make(map[string]spec.Schema)
   217  	sp := newSchemaParser(classificationProg)
   218  	pn := "github.com/go-swagger/go-swagger/fixtures/goparsing/classification/models"
   219  	// pnr := "../fixtures/goparsing/classification/models"
   220  	pkg := classificationProg.Package(pn)
   221  	if assert.NotNil(t, pkg) {
   222  
   223  		fnd := false
   224  		for _, fil := range pkg.Files {
   225  			nm := filepath.Base(classificationProg.Fset.File(fil.Pos()).Name())
   226  			if nm == "order.go" {
   227  				fnd = true
   228  				err := sp.Parse(fil, definitions)
   229  				assert.NoError(t, err)
   230  				break
   231  			}
   232  		}
   233  		assert.True(t, fnd)
   234  		msch, ok := definitions["order"]
   235  		assert.True(t, ok)
   236  		assert.Equal(t, pn, msch.Extensions["x-go-package"])
   237  		assert.Equal(t, "StoreOrder", msch.Extensions["x-go-name"])
   238  	}
   239  }
   240  
   241  func TestEmbeddedTypes(t *testing.T) {
   242  	schema := noModelDefs["ComplexerOne"]
   243  	assertProperty(t, &schema, "integer", "age", "int32", "Age")
   244  	assertProperty(t, &schema, "integer", "id", "int64", "ID")
   245  	assertProperty(t, &schema, "string", "createdAt", "date-time", "CreatedAt")
   246  	assertProperty(t, &schema, "string", "extra", "", "Extra")
   247  	assertProperty(t, &schema, "string", "name", "", "Name")
   248  	assertProperty(t, &schema, "string", "notes", "", "Notes")
   249  }
   250  
   251  func TestArrayOfPointers(t *testing.T) {
   252  	schema := noModelDefs["cars"]
   253  	assertProperty(t, &schema, "array", "cars", "", "Cars")
   254  }
   255  
   256  func TestEmbeddedAllOf(t *testing.T) {
   257  	schema := noModelDefs["AllOfModel"]
   258  
   259  	assert.Len(t, schema.AllOf, 3)
   260  	asch := schema.AllOf[0]
   261  	assertProperty(t, &asch, "integer", "age", "int32", "Age")
   262  	assertProperty(t, &asch, "integer", "id", "int64", "ID")
   263  	assertProperty(t, &asch, "string", "name", "", "Name")
   264  
   265  	asch = schema.AllOf[1]
   266  	assert.Equal(t, "#/definitions/withNotes", asch.Ref.String())
   267  
   268  	asch = schema.AllOf[2]
   269  	assertProperty(t, &asch, "string", "createdAt", "date-time", "CreatedAt")
   270  	assertProperty(t, &asch, "integer", "did", "int64", "DID")
   271  	assertProperty(t, &asch, "string", "cat", "", "Cat")
   272  }
   273  
   274  func TestEmbeddedStarExpr(t *testing.T) {
   275  	schema := noModelDefs["EmbeddedStarExpr"]
   276  
   277  	assertProperty(t, &schema, "integer", "embeddedMember", "int64", "EmbeddedMember")
   278  	assertProperty(t, &schema, "integer", "notEmbedded", "int64", "NotEmbedded")
   279  }
   280  
   281  func TestOverridingOneIgnore(t *testing.T) {
   282  	schema := noModelDefs["OverridingOneIgnore"]
   283  
   284  	assertProperty(t, &schema, "integer", "id", "int64", "ID")
   285  	assertProperty(t, &schema, "string", "name", "", "Name")
   286  	assert.Len(t, schema.Properties, 2)
   287  }
   288  
   289  func TestAliasedTypes(t *testing.T) {
   290  	schema := noModelDefs["OtherTypes"]
   291  	assertRef(t, &schema, "named", "Named", "#/definitions/SomeStringType")
   292  	assertRef(t, &schema, "numbered", "Numbered", "#/definitions/SomeIntType")
   293  	assertProperty(t, &schema, "string", "dated", "date-time", "Dated")
   294  	assertRef(t, &schema, "timed", "Timed", "#/definitions/SomeTimedType")
   295  	assertRef(t, &schema, "petted", "Petted", "#/definitions/SomePettedType")
   296  	assertRef(t, &schema, "somethinged", "Somethinged", "#/definitions/SomethingType")
   297  	assertRef(t, &schema, "strMap", "StrMap", "#/definitions/SomeStringMap")
   298  	assertRef(t, &schema, "strArrMap", "StrArrMap", "#/definitions/SomeArrayStringMap")
   299  
   300  	assertRef(t, &schema, "manyNamed", "ManyNamed", "#/definitions/SomeStringsType")
   301  	assertRef(t, &schema, "manyNumbered", "ManyNumbered", "#/definitions/SomeIntsType")
   302  	assertArrayProperty(t, &schema, "string", "manyDated", "date-time", "ManyDated")
   303  	assertRef(t, &schema, "manyTimed", "ManyTimed", "#/definitions/SomeTimedsType")
   304  	assertRef(t, &schema, "manyPetted", "ManyPetted", "#/definitions/SomePettedsType")
   305  	assertRef(t, &schema, "manySomethinged", "ManySomethinged", "#/definitions/SomethingsType")
   306  
   307  	assertArrayRef(t, &schema, "nameds", "Nameds", "#/definitions/SomeStringType")
   308  	assertArrayRef(t, &schema, "numbereds", "Numbereds", "#/definitions/SomeIntType")
   309  	assertArrayProperty(t, &schema, "string", "dateds", "date-time", "Dateds")
   310  	assertArrayRef(t, &schema, "timeds", "Timeds", "#/definitions/SomeTimedType")
   311  	assertArrayRef(t, &schema, "petteds", "Petteds", "#/definitions/SomePettedType")
   312  	assertArrayRef(t, &schema, "somethingeds", "Somethingeds", "#/definitions/SomethingType")
   313  
   314  	assertRef(t, &schema, "modsNamed", "ModsNamed", "#/definitions/modsSomeStringType")
   315  	assertRef(t, &schema, "modsNumbered", "ModsNumbered", "#/definitions/modsSomeIntType")
   316  	assertProperty(t, &schema, "string", "modsDated", "date-time", "ModsDated")
   317  	assertRef(t, &schema, "modsTimed", "ModsTimed", "#/definitions/modsSomeTimedType")
   318  	assertRef(t, &schema, "modsPetted", "ModsPetted", "#/definitions/modsSomePettedType")
   319  
   320  	assertArrayRef(t, &schema, "modsNameds", "ModsNameds", "#/definitions/modsSomeStringType")
   321  	assertArrayRef(t, &schema, "modsNumbereds", "ModsNumbereds", "#/definitions/modsSomeIntType")
   322  	assertArrayProperty(t, &schema, "string", "modsDateds", "date-time", "ModsDateds")
   323  	assertArrayRef(t, &schema, "modsTimeds", "ModsTimeds", "#/definitions/modsSomeTimedType")
   324  	assertArrayRef(t, &schema, "modsPetteds", "ModsPetteds", "#/definitions/modsSomePettedType")
   325  
   326  	assertRef(t, &schema, "manyModsNamed", "ManyModsNamed", "#/definitions/modsSomeStringsType")
   327  	assertRef(t, &schema, "manyModsNumbered", "ManyModsNumbered", "#/definitions/modsSomeIntsType")
   328  	assertArrayProperty(t, &schema, "string", "manyModsDated", "date-time", "ManyModsDated")
   329  	assertRef(t, &schema, "manyModsTimed", "ManyModsTimed", "#/definitions/modsSomeTimedsType")
   330  	assertRef(t, &schema, "manyModsPetted", "ManyModsPetted", "#/definitions/modsSomePettedsType")
   331  	assertRef(t, &schema, "manyModsPettedPtr", "ManyModsPettedPtr", "#/definitions/modsSomePettedsPtrType")
   332  
   333  	assertProperty(t, &schema, "string", "namedAlias", "", "NamedAlias")
   334  	assertProperty(t, &schema, "integer", "numberedAlias", "int64", "NumberedAlias")
   335  	assertArrayProperty(t, &schema, "string", "namedsAlias", "", "NamedsAlias")
   336  	assertArrayProperty(t, &schema, "integer", "numberedsAlias", "int64", "NumberedsAlias")
   337  }
   338  
   339  func TestParsePrimitiveSchemaProperty(t *testing.T) {
   340  	schema := noModelDefs["PrimateModel"]
   341  	assertProperty(t, &schema, "boolean", "a", "", "A")
   342  	assertProperty(t, &schema, "integer", "b", "int32", "B")
   343  	assertProperty(t, &schema, "string", "c", "", "C")
   344  	assertProperty(t, &schema, "integer", "d", "int64", "D")
   345  	assertProperty(t, &schema, "integer", "e", "int8", "E")
   346  	assertProperty(t, &schema, "integer", "f", "int16", "F")
   347  	assertProperty(t, &schema, "integer", "g", "int32", "G")
   348  	assertProperty(t, &schema, "integer", "h", "int64", "H")
   349  	assertProperty(t, &schema, "integer", "i", "uint64", "I")
   350  	assertProperty(t, &schema, "integer", "j", "uint8", "J")
   351  	assertProperty(t, &schema, "integer", "k", "uint16", "K")
   352  	assertProperty(t, &schema, "integer", "l", "uint32", "L")
   353  	assertProperty(t, &schema, "integer", "m", "uint64", "M")
   354  	assertProperty(t, &schema, "number", "n", "float", "N")
   355  	assertProperty(t, &schema, "number", "o", "double", "O")
   356  	assertProperty(t, &schema, "integer", "p", "uint8", "P")
   357  	assertProperty(t, &schema, "integer", "q", "uint64", "Q")
   358  }
   359  
   360  func TestParseStringFormatSchemaProperty(t *testing.T) {
   361  	schema := noModelDefs["FormattedModel"]
   362  	assertProperty(t, &schema, "string", "a", "byte", "A")
   363  	assertProperty(t, &schema, "string", "b", "creditcard", "B")
   364  	assertProperty(t, &schema, "string", "c", "date", "C")
   365  	assertProperty(t, &schema, "string", "d", "date-time", "D")
   366  	assertProperty(t, &schema, "string", "e", "duration", "E")
   367  	assertProperty(t, &schema, "string", "f", "email", "F")
   368  	assertProperty(t, &schema, "string", "g", "hexcolor", "G")
   369  	assertProperty(t, &schema, "string", "h", "hostname", "H")
   370  	assertProperty(t, &schema, "string", "i", "ipv4", "I")
   371  	assertProperty(t, &schema, "string", "j", "ipv6", "J")
   372  	assertProperty(t, &schema, "string", "k", "isbn", "K")
   373  	assertProperty(t, &schema, "string", "l", "isbn10", "L")
   374  	assertProperty(t, &schema, "string", "m", "isbn13", "M")
   375  	assertProperty(t, &schema, "string", "n", "rgbcolor", "N")
   376  	assertProperty(t, &schema, "string", "o", "ssn", "O")
   377  	assertProperty(t, &schema, "string", "p", "uri", "P")
   378  	assertProperty(t, &schema, "string", "q", "uuid", "Q")
   379  	assertProperty(t, &schema, "string", "r", "uuid3", "R")
   380  	assertProperty(t, &schema, "string", "s", "uuid4", "S")
   381  	assertProperty(t, &schema, "string", "t", "uuid5", "T")
   382  	assertProperty(t, &schema, "string", "u", "mac", "U")
   383  }
   384  
   385  func assertProperty(t testing.TB, schema *spec.Schema, typeName, jsonName, format, goName string) {
   386  	if typeName == "" {
   387  		assert.Empty(t, schema.Properties[jsonName].Type)
   388  	} else {
   389  		if assert.NotEmpty(t, schema.Properties[jsonName].Type) {
   390  			assert.Equal(t, typeName, schema.Properties[jsonName].Type[0])
   391  		}
   392  	}
   393  	if goName == "" {
   394  		assert.Equal(t, nil, schema.Properties[jsonName].Extensions["x-go-name"])
   395  	} else {
   396  		assert.Equal(t, goName, schema.Properties[jsonName].Extensions["x-go-name"])
   397  	}
   398  	assert.Equal(t, format, schema.Properties[jsonName].Format)
   399  }
   400  
   401  func assertRef(t testing.TB, schema *spec.Schema, jsonName, goName, fragment string) {
   402  	assert.Empty(t, schema.Properties[jsonName].Type)
   403  	psch := schema.Properties[jsonName]
   404  	assert.Equal(t, fragment, psch.Ref.String())
   405  }
   406  
   407  func TestParseStructFields(t *testing.T) {
   408  	schema := noModelDefs["SimpleComplexModel"]
   409  	assertProperty(t, &schema, "object", "emb", "", "Emb")
   410  	eSchema := schema.Properties["emb"]
   411  	assertProperty(t, &eSchema, "integer", "cid", "int64", "CID")
   412  	assertProperty(t, &eSchema, "string", "baz", "", "Baz")
   413  
   414  	assertRef(t, &schema, "top", "Top", "#/definitions/Something")
   415  	assertRef(t, &schema, "notSel", "NotSel", "#/definitions/NotSelected")
   416  }
   417  
   418  func TestParsePointerFields(t *testing.T) {
   419  	schema := noModelDefs["Pointdexter"]
   420  
   421  	assertProperty(t, &schema, "integer", "id", "int64", "ID")
   422  	assertProperty(t, &schema, "string", "name", "", "Name")
   423  	assertProperty(t, &schema, "object", "emb", "", "Emb")
   424  	assertProperty(t, &schema, "string", "t", "uuid5", "T")
   425  	eSchema := schema.Properties["emb"]
   426  	assertProperty(t, &eSchema, "integer", "cid", "int64", "CID")
   427  	assertProperty(t, &eSchema, "string", "baz", "", "Baz")
   428  
   429  	assertRef(t, &schema, "top", "Top", "#/definitions/Something")
   430  	assertRef(t, &schema, "notSel", "NotSel", "#/definitions/NotSelected")
   431  }
   432  
   433  func assertArrayProperty(t testing.TB, schema *spec.Schema, typeName, jsonName, format, goName string) {
   434  	prop := schema.Properties[jsonName]
   435  	assert.NotEmpty(t, prop.Type)
   436  	assert.True(t, prop.Type.Contains("array"))
   437  	assert.NotNil(t, prop.Items)
   438  	if typeName != "" {
   439  		assert.Equal(t, typeName, prop.Items.Schema.Type[0])
   440  	}
   441  	assert.Equal(t, goName, prop.Extensions["x-go-name"])
   442  	assert.Equal(t, format, prop.Items.Schema.Format)
   443  }
   444  
   445  func assertArrayRef(t testing.TB, schema *spec.Schema, jsonName, goName, fragment string) {
   446  	assertArrayProperty(t, schema, "", jsonName, "", goName)
   447  	psch := schema.Properties[jsonName].Items.Schema
   448  	assert.Equal(t, fragment, psch.Ref.String())
   449  }
   450  
   451  func TestParseSliceFields(t *testing.T) {
   452  	schema := noModelDefs["SliceAndDice"]
   453  
   454  	assertArrayProperty(t, &schema, "integer", "ids", "int64", "IDs")
   455  	assertArrayProperty(t, &schema, "string", "names", "", "Names")
   456  	assertArrayProperty(t, &schema, "string", "uuids", "uuid", "UUIDs")
   457  	assertArrayProperty(t, &schema, "object", "embs", "", "Embs")
   458  	eSchema := schema.Properties["embs"].Items.Schema
   459  	assertArrayProperty(t, eSchema, "integer", "cid", "int64", "CID")
   460  	assertArrayProperty(t, eSchema, "string", "baz", "", "Baz")
   461  
   462  	assertArrayRef(t, &schema, "tops", "Tops", "#/definitions/Something")
   463  	assertArrayRef(t, &schema, "notSels", "NotSels", "#/definitions/NotSelected")
   464  
   465  	assertArrayProperty(t, &schema, "integer", "ptrIds", "int64", "PtrIDs")
   466  	assertArrayProperty(t, &schema, "string", "ptrNames", "", "PtrNames")
   467  	assertArrayProperty(t, &schema, "string", "ptrUuids", "uuid", "PtrUUIDs")
   468  	assertArrayProperty(t, &schema, "object", "ptrEmbs", "", "PtrEmbs")
   469  	eSchema = schema.Properties["ptrEmbs"].Items.Schema
   470  	assertArrayProperty(t, eSchema, "integer", "ptrCid", "int64", "PtrCID")
   471  	assertArrayProperty(t, eSchema, "string", "ptrBaz", "", "PtrBaz")
   472  
   473  	assertArrayRef(t, &schema, "ptrTops", "PtrTops", "#/definitions/Something")
   474  	assertArrayRef(t, &schema, "ptrNotSels", "PtrNotSels", "#/definitions/NotSelected")
   475  }
   476  
   477  func assertMapProperty(t testing.TB, schema *spec.Schema, typeName, jsonName, format, goName string) {
   478  	prop := schema.Properties[jsonName]
   479  	assert.NotEmpty(t, prop.Type)
   480  	assert.True(t, prop.Type.Contains("object"))
   481  	assert.NotNil(t, prop.AdditionalProperties)
   482  	if typeName != "" {
   483  		assert.Equal(t, typeName, prop.AdditionalProperties.Schema.Type[0])
   484  	}
   485  	assert.Equal(t, goName, prop.Extensions["x-go-name"])
   486  	assert.Equal(t, format, prop.AdditionalProperties.Schema.Format)
   487  }
   488  
   489  func assertMapRef(t testing.TB, schema *spec.Schema, jsonName, goName, fragment string) {
   490  	assertMapProperty(t, schema, "", jsonName, "", goName)
   491  	psch := schema.Properties[jsonName].AdditionalProperties.Schema
   492  	assert.Equal(t, fragment, psch.Ref.String())
   493  }
   494  
   495  func TestParseMapFields(t *testing.T) {
   496  	schema := noModelDefs["MapTastic"]
   497  
   498  	assertMapProperty(t, &schema, "integer", "ids", "int64", "IDs")
   499  	assertMapProperty(t, &schema, "string", "names", "", "Names")
   500  	assertMapProperty(t, &schema, "string", "uuids", "uuid", "UUIDs")
   501  	assertMapProperty(t, &schema, "object", "embs", "", "Embs")
   502  	eSchema := schema.Properties["embs"].AdditionalProperties.Schema
   503  	assertMapProperty(t, eSchema, "integer", "cid", "int64", "CID")
   504  	assertMapProperty(t, eSchema, "string", "baz", "", "Baz")
   505  
   506  	assertMapRef(t, &schema, "tops", "Tops", "#/definitions/Something")
   507  	assertMapRef(t, &schema, "notSels", "NotSels", "#/definitions/NotSelected")
   508  
   509  	assertMapProperty(t, &schema, "integer", "ptrIds", "int64", "PtrIDs")
   510  	assertMapProperty(t, &schema, "string", "ptrNames", "", "PtrNames")
   511  	assertMapProperty(t, &schema, "string", "ptrUuids", "uuid", "PtrUUIDs")
   512  	assertMapProperty(t, &schema, "object", "ptrEmbs", "", "PtrEmbs")
   513  	eSchema = schema.Properties["ptrEmbs"].AdditionalProperties.Schema
   514  	assertMapProperty(t, eSchema, "integer", "ptrCid", "int64", "PtrCID")
   515  	assertMapProperty(t, eSchema, "string", "ptrBaz", "", "PtrBaz")
   516  
   517  	assertMapRef(t, &schema, "ptrTops", "PtrTops", "#/definitions/Something")
   518  	assertMapRef(t, &schema, "ptrNotSels", "PtrNotSels", "#/definitions/NotSelected")
   519  }
   520  
   521  func TestInterfaceField(t *testing.T) {
   522  
   523  	_ = classificationProg
   524  	schema := noModelDefs["Interfaced"]
   525  	assertProperty(t, &schema, "object", "custom_data", "", "CustomData")
   526  }
   527  
   528  func TestStructDiscriminators(t *testing.T) {
   529  	_ = classificationProg
   530  	schema := noModelDefs["animal"]
   531  
   532  	assert.Equal(t, "BaseStruct", schema.Extensions["x-go-name"])
   533  	assert.Equal(t, schema.Discriminator, "jsonClass")
   534  
   535  	sch := noModelDefs["gazelle"]
   536  	assert.Len(t, sch.AllOf, 2)
   537  	cl, _ := sch.Extensions.GetString("x-class")
   538  	assert.Equal(t, "a.b.c.d.E", cl)
   539  	cl, _ = sch.Extensions.GetString("x-go-name")
   540  	assert.Equal(t, "Gazelle", cl)
   541  
   542  	sch = noModelDefs["giraffe"]
   543  	assert.Len(t, sch.AllOf, 2)
   544  	cl, _ = sch.Extensions.GetString("x-class")
   545  	assert.Equal(t, "", cl)
   546  	cl, _ = sch.Extensions.GetString("x-go-name")
   547  	assert.Equal(t, "Giraffe", cl)
   548  
   549  	//sch = noModelDefs["lion"]
   550  
   551  	//b, _ := json.MarshalIndent(sch, "", "  ")
   552  	//fmt.Println(string(b))
   553  
   554  }
   555  
   556  func TestInterfaceDiscriminators(t *testing.T) {
   557  	_ = classificationProg
   558  	schema, ok := noModelDefs["fish"]
   559  	if assert.True(t, ok) && assert.Len(t, schema.AllOf, 5) {
   560  		sch := schema.AllOf[0]
   561  		assert.Len(t, sch.Properties, 1)
   562  		assertProperty(t, &sch, "integer", "id", "int64", "ID")
   563  
   564  		sch = schema.AllOf[1]
   565  		assert.Equal(t, "#/definitions/water", sch.Ref.String())
   566  		sch = schema.AllOf[2]
   567  		assert.Equal(t, "#/definitions/extra", sch.Ref.String())
   568  
   569  		sch = schema.AllOf[3]
   570  		assert.Len(t, sch.Properties, 1)
   571  		assertProperty(t, &sch, "string", "colorName", "", "ColorName")
   572  
   573  		sch = schema.AllOf[4]
   574  		assert.Len(t, sch.Properties, 2)
   575  		assertProperty(t, &sch, "string", "name", "", "Name")
   576  		assertProperty(t, &sch, "string", "jsonClass", "", "StructType")
   577  		assert.Equal(t, "jsonClass", sch.Discriminator)
   578  	}
   579  
   580  	schema, ok = noModelDefs["modelS"]
   581  	if assert.True(t, ok) {
   582  		assert.Len(t, schema.AllOf, 2)
   583  		cl, _ := schema.Extensions.GetString("x-class")
   584  		assert.Equal(t, "com.tesla.models.ModelS", cl)
   585  		cl, _ = schema.Extensions.GetString("x-go-name")
   586  		assert.Equal(t, "ModelS", cl)
   587  
   588  		sch := schema.AllOf[0]
   589  		assert.Equal(t, "#/definitions/TeslaCar", sch.Ref.String())
   590  		sch = schema.AllOf[1]
   591  		assert.Len(t, sch.Properties, 1)
   592  		assertProperty(t, &sch, "string", "edition", "", "Edition")
   593  	}
   594  
   595  	schema, ok = noModelDefs["modelA"]
   596  	if assert.True(t, ok) {
   597  
   598  		cl, _ := schema.Extensions.GetString("x-go-name")
   599  		assert.Equal(t, "ModelA", cl)
   600  
   601  		sch, ok := schema.Properties["Tesla"]
   602  		if assert.True(t, ok) {
   603  			assert.Equal(t, "#/definitions/TeslaCar", sch.Ref.String())
   604  		}
   605  
   606  		assertProperty(t, &schema, "integer", "doors", "int64", "Doors")
   607  	}
   608  }
   609  
   610  func TestStringStructTag(t *testing.T) {
   611  	_ = classificationProg
   612  	sch := noModelDefs["jsonString"]
   613  	assertProperty(t, &sch, "string", "someInt", "int64", "SomeInt")
   614  	assertProperty(t, &sch, "string", "someInt8", "int8", "SomeInt8")
   615  	assertProperty(t, &sch, "string", "someInt16", "int16", "SomeInt16")
   616  	assertProperty(t, &sch, "string", "someInt32", "int32", "SomeInt32")
   617  	assertProperty(t, &sch, "string", "someInt64", "int64", "SomeInt64")
   618  	assertProperty(t, &sch, "string", "someUint", "uint64", "SomeUint")
   619  	assertProperty(t, &sch, "string", "someUint8", "uint8", "SomeUint8")
   620  	assertProperty(t, &sch, "string", "someUint16", "uint16", "SomeUint16")
   621  	assertProperty(t, &sch, "string", "someUint32", "uint32", "SomeUint32")
   622  	assertProperty(t, &sch, "string", "someUint64", "uint64", "SomeUint64")
   623  	assertProperty(t, &sch, "string", "someFloat64", "double", "SomeFloat64")
   624  	assertProperty(t, &sch, "string", "someString", "", "SomeString")
   625  	assertProperty(t, &sch, "string", "someBool", "", "SomeBool")
   626  
   627  	prop, ok := sch.Properties["somethingElse"]
   628  	if assert.True(t, ok) {
   629  		assert.NotEqual(t, "string", prop.Type)
   630  	}
   631  }
   632  
   633  func TestPtrFieldStringStructTag(t *testing.T) {
   634  	_ = classificationProg
   635  	sch := noModelDefs["jsonPtrString"]
   636  	assertProperty(t, &sch, "string", "someInt", "int64", "SomeInt")
   637  	assertProperty(t, &sch, "string", "someInt8", "int8", "SomeInt8")
   638  	assertProperty(t, &sch, "string", "someInt16", "int16", "SomeInt16")
   639  	assertProperty(t, &sch, "string", "someInt32", "int32", "SomeInt32")
   640  	assertProperty(t, &sch, "string", "someInt64", "int64", "SomeInt64")
   641  	assertProperty(t, &sch, "string", "someUint", "uint64", "SomeUint")
   642  	assertProperty(t, &sch, "string", "someUint8", "uint8", "SomeUint8")
   643  	assertProperty(t, &sch, "string", "someUint16", "uint16", "SomeUint16")
   644  	assertProperty(t, &sch, "string", "someUint32", "uint32", "SomeUint32")
   645  	assertProperty(t, &sch, "string", "someUint64", "uint64", "SomeUint64")
   646  	assertProperty(t, &sch, "string", "someFloat64", "double", "SomeFloat64")
   647  	assertProperty(t, &sch, "string", "someString", "", "SomeString")
   648  	assertProperty(t, &sch, "string", "someBool", "", "SomeBool")
   649  
   650  	prop, ok := sch.Properties["somethingElse"]
   651  	if assert.True(t, ok) {
   652  		assert.NotEqual(t, "string", prop.Type)
   653  	}
   654  }
   655  
   656  func TestIgnoredStructField(t *testing.T) {
   657  	_ = classificationProg
   658  	sch := noModelDefs["ignoredFields"]
   659  	assertProperty(t, &sch, "string", "someIncludedField", "", "SomeIncludedField")
   660  	assertProperty(t, &sch, "string", "someErroneouslyIncludedField", "", "SomeErroneouslyIncludedField")
   661  	assert.Len(t, sch.Properties, 2)
   662  }
   663  
   664  func TestAliasedModels(t *testing.T) {
   665  	_, defs := extraModelsClassifier(t)
   666  
   667  	names := []string{
   668  		"SomeStringType",
   669  		"SomeIntType",
   670  		"SomeTimeType",
   671  		"SomeTimedType",
   672  		"SomePettedType",
   673  		"SomethingType",
   674  		"SomeStringsType",
   675  		"SomeIntsType",
   676  		"SomeTimesType",
   677  		"SomeTimedsType",
   678  		"SomePettedsType",
   679  		"SomethingsType",
   680  		"SomeObject",
   681  	}
   682  	for k := range defs {
   683  		for i, b := range names {
   684  			if b == k {
   685  				names = append(names[:i], names[i+1:]...)
   686  			}
   687  		}
   688  	}
   689  	if assert.Empty(t, names) {
   690  		// single value types
   691  		assertDefinition(t, defs, "SomeStringType", "string", "", "")
   692  		assertDefinition(t, defs, "SomeIntType", "integer", "int64", "")
   693  		assertDefinition(t, defs, "SomeTimeType", "string", "date-time", "")
   694  		assertDefinition(t, defs, "SomeTimedType", "string", "date-time", "")
   695  		assertRefDefinition(t, defs, "SomePettedType", "#/definitions/pet", "")
   696  		assertRefDefinition(t, defs, "SomethingType", "#/definitions/Something", "")
   697  
   698  		// slice types
   699  		assertArrayDefinition(t, defs, "SomeStringsType", "string", "", "")
   700  		assertArrayDefinition(t, defs, "SomeIntsType", "integer", "int64", "")
   701  		assertArrayDefinition(t, defs, "SomeTimesType", "string", "date-time", "")
   702  		assertArrayDefinition(t, defs, "SomeTimedsType", "string", "date-time", "")
   703  		assertArrayWithRefDefinition(t, defs, "SomePettedsType", "#/definitions/pet", "")
   704  		assertArrayWithRefDefinition(t, defs, "SomethingsType", "#/definitions/Something", "")
   705  
   706  		// map types
   707  		assertMapDefinition(t, defs, "SomeObject", "object", "", "")
   708  		assertMapDefinition(t, defs, "SomeStringMap", "string", "", "")
   709  		assertMapDefinition(t, defs, "SomeIntMap", "integer", "int64", "")
   710  		assertMapDefinition(t, defs, "SomeTimeMap", "string", "date-time", "")
   711  		assertMapDefinition(t, defs, "SomeTimedMap", "string", "date-time", "")
   712  		assertMapWithRefDefinition(t, defs, "SomePettedMap", "#/definitions/pet", "")
   713  		assertMapWithRefDefinition(t, defs, "SomeSomethingMap", "#/definitions/Something", "")
   714  	}
   715  }
   716  
   717  func assertDefinition(t testing.TB, defs map[string]spec.Schema, defName, typeName, formatName, goName string) {
   718  	schema, ok := defs[defName]
   719  	if assert.True(t, ok) {
   720  
   721  		if assert.NotEmpty(t, schema.Type) {
   722  			assert.Equal(t, typeName, schema.Type[0])
   723  			if goName != "" {
   724  				assert.Equal(t, goName, schema.Extensions["x-go-name"])
   725  			} else {
   726  				assert.Nil(t, schema.Extensions["x-go-name"])
   727  			}
   728  			assert.Equal(t, formatName, schema.Format)
   729  		}
   730  	}
   731  }
   732  
   733  func assertMapDefinition(t testing.TB, defs map[string]spec.Schema, defName, typeName, formatName, goName string) {
   734  	schema, ok := defs[defName]
   735  	if assert.True(t, ok) {
   736  		if assert.NotEmpty(t, schema.Type) {
   737  			assert.Equal(t, "object", schema.Type[0])
   738  			adl := schema.AdditionalProperties
   739  			if assert.NotNil(t, adl) && assert.NotNil(t, adl.Schema) {
   740  				assert.Equal(t, typeName, adl.Schema.Type[0])
   741  				assert.Equal(t, formatName, adl.Schema.Format)
   742  			}
   743  			if goName != "" {
   744  				assert.Equal(t, goName, schema.Extensions["x-go-name"])
   745  			} else {
   746  				assert.Nil(t, schema.Extensions["x-go-name"])
   747  			}
   748  		}
   749  	}
   750  }
   751  
   752  func assertMapWithRefDefinition(t testing.TB, defs map[string]spec.Schema, defName, refURL, goName string) {
   753  	schema, ok := defs[defName]
   754  	if assert.True(t, ok) {
   755  		if assert.NotEmpty(t, schema.Type) {
   756  			assert.Equal(t, "object", schema.Type[0])
   757  			adl := schema.AdditionalProperties
   758  			if assert.NotNil(t, adl) && assert.NotNil(t, adl.Schema) {
   759  				if assert.NotZero(t, adl.Schema.Ref) {
   760  					assert.Equal(t, refURL, adl.Schema.Ref.String())
   761  				}
   762  			}
   763  			if goName != "" {
   764  				assert.Equal(t, goName, schema.Extensions["x-go-name"])
   765  			} else {
   766  				assert.Nil(t, schema.Extensions["x-go-name"])
   767  			}
   768  		}
   769  	}
   770  }
   771  
   772  func assertArrayDefinition(t testing.TB, defs map[string]spec.Schema, defName, typeName, formatName, goName string) {
   773  	schema, ok := defs[defName]
   774  	if assert.True(t, ok) {
   775  		if assert.NotEmpty(t, schema.Type) {
   776  			assert.Equal(t, "array", schema.Type[0])
   777  			adl := schema.Items
   778  			if assert.NotNil(t, adl) && assert.NotNil(t, adl.Schema) {
   779  				assert.Equal(t, typeName, adl.Schema.Type[0])
   780  				assert.Equal(t, formatName, adl.Schema.Format)
   781  			}
   782  			if goName != "" {
   783  				assert.Equal(t, goName, schema.Extensions["x-go-name"])
   784  			} else {
   785  				assert.Nil(t, schema.Extensions["x-go-name"])
   786  			}
   787  		}
   788  	}
   789  }
   790  
   791  func assertArrayWithRefDefinition(t testing.TB, defs map[string]spec.Schema, defName, refURL, goName string) {
   792  	schema, ok := defs[defName]
   793  	if assert.True(t, ok) {
   794  		if assert.NotEmpty(t, schema.Type) {
   795  			assert.Equal(t, "array", schema.Type[0])
   796  			adl := schema.Items
   797  			if assert.NotNil(t, adl) && assert.NotNil(t, adl.Schema) {
   798  				if assert.NotZero(t, adl.Schema.Ref) {
   799  					assert.Equal(t, refURL, adl.Schema.Ref.String())
   800  				}
   801  			}
   802  			if goName != "" {
   803  				assert.Equal(t, goName, schema.Extensions["x-go-name"])
   804  			} else {
   805  				assert.Nil(t, schema.Extensions["x-go-name"])
   806  			}
   807  		}
   808  	}
   809  }
   810  
   811  func assertRefDefinition(t testing.TB, defs map[string]spec.Schema, defName, refURL, goName string) {
   812  	schema, ok := defs[defName]
   813  	if assert.True(t, ok) {
   814  		if assert.NotZero(t, schema.Ref) {
   815  			url := schema.Ref.String()
   816  			assert.Equal(t, refURL, url)
   817  			if goName != "" {
   818  				assert.Equal(t, goName, schema.Extensions["x-go-name"])
   819  			} else {
   820  				assert.Nil(t, schema.Extensions["x-go-name"])
   821  			}
   822  		}
   823  	}
   824  }
   825  
   826  func TestAddExtension(t *testing.T) {
   827  	ve := &spec.VendorExtensible{
   828  		Extensions: make(spec.Extensions),
   829  	}
   830  
   831  	key := "x-go-name"
   832  	value := "Name"
   833  	addExtension(ve, key, value)
   834  	assert.Equal(t, value, ve.Extensions[key].(string))
   835  
   836  	key2 := "x-go-package"
   837  	value2 := "schema"
   838  	os.Setenv("SWAGGER_GENERATE_EXTENSION", "true")
   839  	addExtension(ve, key2, value2)
   840  	assert.Equal(t, value2, ve.Extensions[key2].(string))
   841  
   842  	key3 := "x-go-class"
   843  	value3 := "Spec"
   844  	os.Setenv("SWAGGER_GENERATE_EXTENSION", "false")
   845  	addExtension(ve, key3, value3)
   846  	assert.Equal(t, nil, ve.Extensions[key3])
   847  }