github.com/go-swagger/go-swagger@v0.31.0/codescan/schema_test.go (about)

     1  package codescan
     2  
     3  import (
     4  	"os"
     5  	"testing"
     6  
     7  	"github.com/go-openapi/spec"
     8  	"github.com/stretchr/testify/assert"
     9  	"github.com/stretchr/testify/require"
    10  )
    11  
    12  func TestSchemaBuilder_Struct_Tag(t *testing.T) {
    13  	sctx := loadPetstorePkgsCtx(t)
    14  	var td *entityDecl
    15  	for k := range sctx.app.Models {
    16  		if k.Name != "Tag" {
    17  			continue
    18  		}
    19  		td = sctx.app.Models[k]
    20  		break
    21  	}
    22  	require.NotNil(t, td)
    23  
    24  	prs := &schemaBuilder{
    25  		ctx:  sctx,
    26  		decl: td,
    27  	}
    28  	result := make(map[string]spec.Schema)
    29  	require.NoError(t, prs.Build(result))
    30  }
    31  
    32  func TestSchemaBuilder_Struct_Pet(t *testing.T) {
    33  	// Debug = true
    34  	// defer func() { Debug = false }()
    35  
    36  	sctx := loadPetstorePkgsCtx(t)
    37  	var td *entityDecl
    38  	for k := range sctx.app.Models {
    39  		if k.Name != "Pet" {
    40  			continue
    41  		}
    42  		td = sctx.app.Models[k]
    43  		break
    44  	}
    45  	require.NotNil(t, td)
    46  
    47  	prs := &schemaBuilder{
    48  		ctx:  sctx,
    49  		decl: td,
    50  	}
    51  	result := make(map[string]spec.Schema)
    52  	require.NoError(t, prs.Build(result))
    53  }
    54  
    55  func TestSchemaBuilder_Struct_Order(t *testing.T) {
    56  	// Debug = true
    57  	// defer func() { Debug = false }()
    58  
    59  	sctx := loadPetstorePkgsCtx(t)
    60  	var td *entityDecl
    61  	for k := range sctx.app.Models {
    62  		if k.Name != "Order" {
    63  			continue
    64  		}
    65  		td = sctx.app.Models[k]
    66  		break
    67  	}
    68  	require.NotNil(t, td)
    69  
    70  	prs := &schemaBuilder{
    71  		ctx:  sctx,
    72  		decl: td,
    73  	}
    74  	result := make(map[string]spec.Schema)
    75  	require.NoError(t, prs.Build(result))
    76  }
    77  
    78  func TestSchemaBuilder(t *testing.T) {
    79  	sctx := loadClassificationPkgsCtx(t)
    80  	decl := getClassificationModel(sctx, "NoModel")
    81  	require.NotNil(t, decl)
    82  	prs := &schemaBuilder{
    83  		ctx:  sctx,
    84  		decl: decl,
    85  	}
    86  	models := make(map[string]spec.Schema)
    87  	require.NoError(t, prs.Build(models))
    88  	schema := models["NoModel"]
    89  
    90  	assert.Equal(t, spec.StringOrArray([]string{"object"}), schema.Type)
    91  	assert.Equal(t, "NoModel is a struct without an annotation.", schema.Title)
    92  	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)
    93  	assert.Len(t, schema.Required, 3)
    94  	assert.Len(t, schema.Properties, 12)
    95  
    96  	assertProperty(t, &schema, "integer", "id", "int64", "ID")
    97  	prop, ok := schema.Properties["id"]
    98  	assert.Equal(t, "ID of this no model instance.\nids in this application start at 11 and are smaller than 1000", prop.Description)
    99  	assert.True(t, ok, "should have had an 'id' property")
   100  	assert.EqualValues(t, 1000, *prop.Maximum)
   101  	assert.True(t, prop.ExclusiveMaximum, "'id' should have had an exclusive maximum")
   102  	assert.NotNil(t, prop.Minimum)
   103  	assert.EqualValues(t, 10, *prop.Minimum)
   104  	assert.True(t, prop.ExclusiveMinimum, "'id' should have had an exclusive minimum")
   105  	assert.Equal(t, 11, prop.Default, "ID default value is incorrect")
   106  
   107  	assertProperty(t, &schema, "string", "NoNameOmitEmpty", "", "")
   108  	prop, ok = schema.Properties["NoNameOmitEmpty"]
   109  	assert.Equal(t, "A field which has omitempty set but no name", prop.Description)
   110  	assert.True(t, ok, "should have had an 'NoNameOmitEmpty' property")
   111  
   112  	assertProperty(t, &schema, "string", "noteb64", "byte", "Note")
   113  	prop, ok = schema.Properties["noteb64"]
   114  	assert.True(t, ok, "should have a 'noteb64' property")
   115  	assert.Nil(t, prop.Items)
   116  
   117  	assertProperty(t, &schema, "integer", "score", "int32", "Score")
   118  	prop, ok = schema.Properties["score"]
   119  	assert.Equal(t, "The Score of this model", prop.Description)
   120  	assert.True(t, ok, "should have had a 'score' property")
   121  	assert.EqualValues(t, 45, *prop.Maximum)
   122  	assert.False(t, prop.ExclusiveMaximum, "'score' should not have had an exclusive maximum")
   123  	assert.NotNil(t, prop.Minimum)
   124  	assert.EqualValues(t, 3, *prop.Minimum)
   125  	assert.False(t, prop.ExclusiveMinimum, "'score' should not have had an exclusive minimum")
   126  	assert.Equal(t, 27, prop.Example)
   127  
   128  	expectedNameExtensions := spec.Extensions{
   129  		"x-go-name": "Name",
   130  		"x-property-array": []interface{}{
   131  			"value1",
   132  			"value2",
   133  		},
   134  		"x-property-array-obj": []interface{}{
   135  			map[string]interface{}{
   136  				"name":  "obj",
   137  				"value": "field",
   138  			},
   139  		},
   140  		"x-property-value": "value",
   141  	}
   142  
   143  	assertProperty(t, &schema, "string", "name", "", "Name")
   144  	prop, ok = schema.Properties["name"]
   145  	assert.True(t, ok)
   146  	assert.Equal(t, "Name of this no model instance", prop.Description)
   147  	assert.EqualValues(t, 4, *prop.MinLength)
   148  	assert.EqualValues(t, 50, *prop.MaxLength)
   149  	assert.Equal(t, "[A-Za-z0-9-.]*", prop.Pattern)
   150  	assert.EqualValues(t, expectedNameExtensions, prop.Extensions)
   151  
   152  	assertProperty(t, &schema, "string", "created", "date-time", "Created")
   153  	prop, ok = schema.Properties["created"]
   154  	assert.Equal(t, "Created holds the time when this entry was created", prop.Description)
   155  	assert.True(t, ok, "should have a 'created' property")
   156  	assert.True(t, prop.ReadOnly, "'created' should be read only")
   157  
   158  	assertProperty(t, &schema, "string", "gocreated", "date-time", "GoTimeCreated")
   159  	prop, ok = schema.Properties["gocreated"]
   160  	assert.Equal(t, "GoTimeCreated holds the time when this entry was created in go time.Time", prop.Description)
   161  	assert.True(t, ok, "should have a 'gocreated' property")
   162  
   163  	assertArrayProperty(t, &schema, "string", "foo_slice", "", "FooSlice")
   164  	prop, ok = schema.Properties["foo_slice"]
   165  	assert.Equal(t, "a FooSlice has foos which are strings", prop.Description)
   166  	assert.True(t, ok, "should have a 'foo_slice' property")
   167  	assert.NotNil(t, prop.Items, "foo_slice should have had an items property")
   168  	assert.NotNil(t, prop.Items.Schema, "foo_slice.items should have had a schema property")
   169  	assert.True(t, prop.UniqueItems, "'foo_slice' should have unique items")
   170  	assert.EqualValues(t, 3, *prop.MinItems, "'foo_slice' should have had 3 min items")
   171  	assert.EqualValues(t, 10, *prop.MaxItems, "'foo_slice' should have had 10 max items")
   172  	itprop := prop.Items.Schema
   173  	assert.EqualValues(t, 3, *itprop.MinLength, "'foo_slice.items.minLength' should have been 3")
   174  	assert.EqualValues(t, 10, *itprop.MaxLength, "'foo_slice.items.maxLength' should have been 10")
   175  	assert.EqualValues(t, "\\w+", itprop.Pattern, "'foo_slice.items.pattern' should have \\w+")
   176  
   177  	assertArrayProperty(t, &schema, "string", "time_slice", "date-time", "TimeSlice")
   178  	prop, ok = schema.Properties["time_slice"]
   179  	assert.Equal(t, "a TimeSlice is a slice of times", prop.Description)
   180  	assert.True(t, ok, "should have a 'time_slice' property")
   181  	assert.NotNil(t, prop.Items, "time_slice should have had an items property")
   182  	assert.NotNil(t, prop.Items.Schema, "time_slice.items should have had a schema property")
   183  	assert.True(t, prop.UniqueItems, "'time_slice' should have unique items")
   184  	assert.EqualValues(t, 3, *prop.MinItems, "'time_slice' should have had 3 min items")
   185  	assert.EqualValues(t, 10, *prop.MaxItems, "'time_slice' should have had 10 max items")
   186  
   187  	assertArrayProperty(t, &schema, "array", "bar_slice", "", "BarSlice")
   188  	prop, ok = schema.Properties["bar_slice"]
   189  	assert.Equal(t, "a BarSlice has bars which are strings", prop.Description)
   190  	assert.True(t, ok, "should have a 'bar_slice' property")
   191  	assert.NotNil(t, prop.Items, "bar_slice should have had an items property")
   192  	assert.NotNil(t, prop.Items.Schema, "bar_slice.items should have had a schema property")
   193  	assert.True(t, prop.UniqueItems, "'bar_slice' should have unique items")
   194  	assert.EqualValues(t, 3, *prop.MinItems, "'bar_slice' should have had 3 min items")
   195  	assert.EqualValues(t, 10, *prop.MaxItems, "'bar_slice' should have had 10 max items")
   196  	itprop = prop.Items.Schema
   197  	if assert.NotNil(t, itprop) {
   198  		assert.EqualValues(t, 4, *itprop.MinItems, "'bar_slice.items.minItems' should have been 4")
   199  		assert.EqualValues(t, 9, *itprop.MaxItems, "'bar_slice.items.maxItems' should have been 9")
   200  		itprop2 := itprop.Items.Schema
   201  		if assert.NotNil(t, itprop2) {
   202  			assert.EqualValues(t, 5, *itprop2.MinItems, "'bar_slice.items.items.minItems' should have been 5")
   203  			assert.EqualValues(t, 8, *itprop2.MaxItems, "'bar_slice.items.items.maxItems' should have been 8")
   204  			itprop3 := itprop2.Items.Schema
   205  			if assert.NotNil(t, itprop3) {
   206  				assert.EqualValues(t, 3, *itprop3.MinLength, "'bar_slice.items.items.items.minLength' should have been 3")
   207  				assert.EqualValues(t, 10, *itprop3.MaxLength, "'bar_slice.items.items.items.maxLength' should have been 10")
   208  				assert.EqualValues(t, "\\w+", itprop3.Pattern, "'bar_slice.items.items.items.pattern' should have \\w+")
   209  			}
   210  		}
   211  	}
   212  
   213  	assertArrayProperty(t, &schema, "array", "deep_time_slice", "", "DeepTimeSlice")
   214  	prop, ok = schema.Properties["deep_time_slice"]
   215  	assert.Equal(t, "a DeepSlice has bars which are time", prop.Description)
   216  	assert.True(t, ok, "should have a 'deep_time_slice' property")
   217  	assert.NotNil(t, prop.Items, "deep_time_slice should have had an items property")
   218  	assert.NotNil(t, prop.Items.Schema, "deep_time_slice.items should have had a schema property")
   219  	assert.True(t, prop.UniqueItems, "'deep_time_slice' should have unique items")
   220  	assert.EqualValues(t, 3, *prop.MinItems, "'deep_time_slice' should have had 3 min items")
   221  	assert.EqualValues(t, 10, *prop.MaxItems, "'deep_time_slice' should have had 10 max items")
   222  	itprop = prop.Items.Schema
   223  	if assert.NotNil(t, itprop) {
   224  		assert.EqualValues(t, 4, *itprop.MinItems, "'deep_time_slice.items.minItems' should have been 4")
   225  		assert.EqualValues(t, 9, *itprop.MaxItems, "'deep_time_slice.items.maxItems' should have been 9")
   226  		itprop2 := itprop.Items.Schema
   227  		if assert.NotNil(t, itprop2) {
   228  			assert.EqualValues(t, 5, *itprop2.MinItems, "'deep_time_slice.items.items.minItems' should have been 5")
   229  			assert.EqualValues(t, 8, *itprop2.MaxItems, "'deep_time_slice.items.items.maxItems' should have been 8")
   230  			itprop3 := itprop2.Items.Schema
   231  			assert.NotNil(t, itprop3)
   232  		}
   233  	}
   234  
   235  	assertArrayProperty(t, &schema, "object", "items", "", "Items")
   236  	prop, ok = schema.Properties["items"]
   237  	assert.True(t, ok, "should have an 'items' slice")
   238  	assert.NotNil(t, prop.Items, "items should have had an items property")
   239  	assert.NotNil(t, prop.Items.Schema, "items.items should have had a schema property")
   240  	itprop = prop.Items.Schema
   241  	assert.Len(t, itprop.Properties, 5)
   242  	assert.Len(t, itprop.Required, 4)
   243  	assertProperty(t, itprop, "integer", "id", "int32", "ID")
   244  	iprop, ok := itprop.Properties["id"]
   245  	assert.True(t, ok)
   246  	assert.Equal(t, "ID of this no model instance.\nids in this application start at 11 and are smaller than 1000", iprop.Description)
   247  	assert.EqualValues(t, 1000, *iprop.Maximum)
   248  	assert.True(t, iprop.ExclusiveMaximum, "'id' should have had an exclusive maximum")
   249  	assert.NotNil(t, iprop.Minimum)
   250  	assert.EqualValues(t, 10, *iprop.Minimum)
   251  	assert.True(t, iprop.ExclusiveMinimum, "'id' should have had an exclusive minimum")
   252  	assert.Equal(t, 11, iprop.Default, "ID default value is incorrect")
   253  
   254  	assertRef(t, itprop, "pet", "Pet", "#/definitions/pet")
   255  	iprop, ok = itprop.Properties["pet"]
   256  	assert.True(t, ok)
   257  	if itprop.Ref.String() != "" {
   258  		assert.Equal(t, "The Pet to add to this NoModel items bucket.\nPets can appear more than once in the bucket", iprop.Description)
   259  	}
   260  
   261  	assertProperty(t, itprop, "integer", "quantity", "int16", "Quantity")
   262  	iprop, ok = itprop.Properties["quantity"]
   263  	assert.True(t, ok)
   264  	assert.Equal(t, "The amount of pets to add to this bucket.", iprop.Description)
   265  	assert.EqualValues(t, 1, *iprop.Minimum)
   266  	assert.EqualValues(t, 10, *iprop.Maximum)
   267  
   268  	assertProperty(t, itprop, "string", "expiration", "date-time", "Expiration")
   269  	iprop, ok = itprop.Properties["expiration"]
   270  	assert.True(t, ok)
   271  	assert.Equal(t, "A dummy expiration date.", iprop.Description)
   272  
   273  	assertProperty(t, itprop, "string", "notes", "", "Notes")
   274  	iprop, ok = itprop.Properties["notes"]
   275  	assert.True(t, ok)
   276  	assert.Equal(t, "Notes to add to this item.\nThis can be used to add special instructions.", iprop.Description)
   277  
   278  	decl2 := getClassificationModel(sctx, "StoreOrder")
   279  	require.NotNil(t, decl2)
   280  	require.NoError(t, (&schemaBuilder{decl: decl2, ctx: sctx}).Build(models))
   281  	msch, ok := models["order"]
   282  	pn := "github.com/go-swagger/go-swagger/fixtures/goparsing/classification/models"
   283  	assert.True(t, ok)
   284  	assert.Equal(t, pn, msch.Extensions["x-go-package"])
   285  	assert.Equal(t, "StoreOrder", msch.Extensions["x-go-name"])
   286  }
   287  
   288  func TestSchemaBuilder_AddExtensions(t *testing.T) {
   289  	sctx := loadClassificationPkgsCtx(t)
   290  	models := make(map[string]spec.Schema)
   291  	decl := getClassificationModel(sctx, "StoreOrder")
   292  	require.NotNil(t, decl)
   293  	require.NoError(t, (&schemaBuilder{decl: decl, ctx: sctx}).Build(models))
   294  
   295  	msch, ok := models["order"]
   296  	pn := "github.com/go-swagger/go-swagger/fixtures/goparsing/classification/models"
   297  	assert.True(t, ok)
   298  	assert.Equal(t, pn, msch.Extensions["x-go-package"])
   299  	assert.Equal(t, "StoreOrder", msch.Extensions["x-go-name"])
   300  	assert.Equal(t, "StoreOrder represents an order in this application.", msch.Title)
   301  }
   302  
   303  func TestTextMarhalCustomType(t *testing.T) {
   304  	sctx := loadClassificationPkgsCtx(t)
   305  	decl := getClassificationModel(sctx, "TextMarshalModel")
   306  	require.NotNil(t, decl)
   307  	prs := &schemaBuilder{
   308  		ctx:  sctx,
   309  		decl: decl,
   310  	}
   311  	models := make(map[string]spec.Schema)
   312  	require.NoError(t, prs.Build(models))
   313  	schema := models["TextMarshalModel"]
   314  	assertProperty(t, &schema, "string", "id", "uuid", "ID")
   315  	assertArrayProperty(t, &schema, "string", "ids", "uuid", "IDs")
   316  	assertProperty(t, &schema, "string", "struct", "", "Struct")
   317  	assertProperty(t, &schema, "string", "map", "", "Map")
   318  	assertMapProperty(t, &schema, "string", "mapUUID", "uuid", "MapUUID")
   319  	assertRef(t, &schema, "url", "URL", "#/definitions/URL")
   320  	assertProperty(t, &schema, "string", "time", "date-time", "Time")
   321  	assertProperty(t, &schema, "string", "structStrfmt", "date-time", "StructStrfmt")
   322  	assertProperty(t, &schema, "string", "structStrfmtPtr", "date-time", "StructStrfmtPtr")
   323  	assertProperty(t, &schema, "string", "customUrl", "url", "CustomURL")
   324  }
   325  
   326  func TestEmbeddedTypes(t *testing.T) {
   327  	sctx := loadClassificationPkgsCtx(t)
   328  	decl := getClassificationModel(sctx, "ComplexerOne")
   329  	require.NotNil(t, decl)
   330  	prs := &schemaBuilder{
   331  		ctx:  sctx,
   332  		decl: decl,
   333  	}
   334  	models := make(map[string]spec.Schema)
   335  	require.NoError(t, prs.Build(models))
   336  	schema := models["ComplexerOne"]
   337  	assertProperty(t, &schema, "integer", "age", "int32", "Age")
   338  	assertProperty(t, &schema, "integer", "id", "int64", "ID")
   339  	assertProperty(t, &schema, "string", "createdAt", "date-time", "CreatedAt")
   340  	assertProperty(t, &schema, "string", "extra", "", "Extra")
   341  	assertProperty(t, &schema, "string", "name", "", "Name")
   342  	assertProperty(t, &schema, "string", "notes", "", "Notes")
   343  }
   344  
   345  func TestParsePrimitiveSchemaProperty(t *testing.T) {
   346  	sctx := loadClassificationPkgsCtx(t)
   347  	decl := getClassificationModel(sctx, "PrimateModel")
   348  	require.NotNil(t, decl)
   349  	prs := &schemaBuilder{
   350  		ctx:  sctx,
   351  		decl: decl,
   352  	}
   353  	models := make(map[string]spec.Schema)
   354  	require.NoError(t, prs.Build(models))
   355  
   356  	schema := models["PrimateModel"]
   357  	assertProperty(t, &schema, "boolean", "a", "", "A")
   358  	assertProperty(t, &schema, "integer", "b", "int32", "B")
   359  	assertProperty(t, &schema, "string", "c", "", "C")
   360  	assertProperty(t, &schema, "integer", "d", "int64", "D")
   361  	assertProperty(t, &schema, "integer", "e", "int8", "E")
   362  	assertProperty(t, &schema, "integer", "f", "int16", "F")
   363  	assertProperty(t, &schema, "integer", "g", "int32", "G")
   364  	assertProperty(t, &schema, "integer", "h", "int64", "H")
   365  	assertProperty(t, &schema, "integer", "i", "uint64", "I")
   366  	assertProperty(t, &schema, "integer", "j", "uint8", "J")
   367  	assertProperty(t, &schema, "integer", "k", "uint16", "K")
   368  	assertProperty(t, &schema, "integer", "l", "uint32", "L")
   369  	assertProperty(t, &schema, "integer", "m", "uint64", "M")
   370  	assertProperty(t, &schema, "number", "n", "float", "N")
   371  	assertProperty(t, &schema, "number", "o", "double", "O")
   372  	assertProperty(t, &schema, "integer", "p", "uint8", "P")
   373  	assertProperty(t, &schema, "integer", "q", "uint64", "Q")
   374  }
   375  
   376  func TestParseStringFormatSchemaProperty(t *testing.T) {
   377  	sctx := loadClassificationPkgsCtx(t)
   378  	decl := getClassificationModel(sctx, "FormattedModel")
   379  	require.NotNil(t, decl)
   380  	prs := &schemaBuilder{
   381  		ctx:  sctx,
   382  		decl: decl,
   383  	}
   384  	models := make(map[string]spec.Schema)
   385  	require.NoError(t, prs.Build(models))
   386  
   387  	schema := models["FormattedModel"]
   388  	assertProperty(t, &schema, "string", "a", "byte", "A")
   389  	assertProperty(t, &schema, "string", "b", "creditcard", "B")
   390  	assertProperty(t, &schema, "string", "c", "date", "C")
   391  	assertProperty(t, &schema, "string", "d", "date-time", "D")
   392  	assertProperty(t, &schema, "string", "e", "duration", "E")
   393  	assertProperty(t, &schema, "string", "f", "email", "F")
   394  	assertProperty(t, &schema, "string", "g", "hexcolor", "G")
   395  	assertProperty(t, &schema, "string", "h", "hostname", "H")
   396  	assertProperty(t, &schema, "string", "i", "ipv4", "I")
   397  	assertProperty(t, &schema, "string", "j", "ipv6", "J")
   398  	assertProperty(t, &schema, "string", "k", "isbn", "K")
   399  	assertProperty(t, &schema, "string", "l", "isbn10", "L")
   400  	assertProperty(t, &schema, "string", "m", "isbn13", "M")
   401  	assertProperty(t, &schema, "string", "n", "rgbcolor", "N")
   402  	assertProperty(t, &schema, "string", "o", "ssn", "O")
   403  	assertProperty(t, &schema, "string", "p", "uri", "P")
   404  	assertProperty(t, &schema, "string", "q", "uuid", "Q")
   405  	assertProperty(t, &schema, "string", "r", "uuid3", "R")
   406  	assertProperty(t, &schema, "string", "s", "uuid4", "S")
   407  	assertProperty(t, &schema, "string", "t", "uuid5", "T")
   408  	assertProperty(t, &schema, "string", "u", "mac", "U")
   409  }
   410  
   411  func TestStringStructTag(t *testing.T) {
   412  	sctx := loadClassificationPkgsCtx(t)
   413  	decl := getClassificationModel(sctx, "JSONString")
   414  	require.NotNil(t, decl)
   415  	prs := &schemaBuilder{
   416  		ctx:  sctx,
   417  		decl: decl,
   418  	}
   419  	models := make(map[string]spec.Schema)
   420  	require.NoError(t, prs.Build(models))
   421  
   422  	sch := models["jsonString"]
   423  	assertProperty(t, &sch, "string", "someInt", "int64", "SomeInt")
   424  	assertProperty(t, &sch, "string", "someInt8", "int8", "SomeInt8")
   425  	assertProperty(t, &sch, "string", "someInt16", "int16", "SomeInt16")
   426  	assertProperty(t, &sch, "string", "someInt32", "int32", "SomeInt32")
   427  	assertProperty(t, &sch, "string", "someInt64", "int64", "SomeInt64")
   428  	assertProperty(t, &sch, "string", "someUint", "uint64", "SomeUint")
   429  	assertProperty(t, &sch, "string", "someUint8", "uint8", "SomeUint8")
   430  	assertProperty(t, &sch, "string", "someUint16", "uint16", "SomeUint16")
   431  	assertProperty(t, &sch, "string", "someUint32", "uint32", "SomeUint32")
   432  	assertProperty(t, &sch, "string", "someUint64", "uint64", "SomeUint64")
   433  	assertProperty(t, &sch, "string", "someFloat64", "double", "SomeFloat64")
   434  	assertProperty(t, &sch, "string", "someString", "", "SomeString")
   435  	assertProperty(t, &sch, "string", "someBool", "", "SomeBool")
   436  	assertProperty(t, &sch, "string", "SomeDefaultInt", "int64", "")
   437  
   438  	prop, ok := sch.Properties["somethingElse"]
   439  	if assert.True(t, ok) {
   440  		assert.NotEqual(t, "string", prop.Type)
   441  	}
   442  }
   443  
   444  func TestPtrFieldStringStructTag(t *testing.T) {
   445  	sctx := loadClassificationPkgsCtx(t)
   446  	decl := getClassificationModel(sctx, "JSONPtrString")
   447  	require.NotNil(t, decl)
   448  	prs := &schemaBuilder{
   449  		ctx:  sctx,
   450  		decl: decl,
   451  	}
   452  	models := make(map[string]spec.Schema)
   453  	require.NoError(t, prs.Build(models))
   454  
   455  	sch := models["jsonPtrString"]
   456  	assertProperty(t, &sch, "string", "someInt", "int64", "SomeInt")
   457  	assertProperty(t, &sch, "string", "someInt8", "int8", "SomeInt8")
   458  	assertProperty(t, &sch, "string", "someInt16", "int16", "SomeInt16")
   459  	assertProperty(t, &sch, "string", "someInt32", "int32", "SomeInt32")
   460  	assertProperty(t, &sch, "string", "someInt64", "int64", "SomeInt64")
   461  	assertProperty(t, &sch, "string", "someUint", "uint64", "SomeUint")
   462  	assertProperty(t, &sch, "string", "someUint8", "uint8", "SomeUint8")
   463  	assertProperty(t, &sch, "string", "someUint16", "uint16", "SomeUint16")
   464  	assertProperty(t, &sch, "string", "someUint32", "uint32", "SomeUint32")
   465  	assertProperty(t, &sch, "string", "someUint64", "uint64", "SomeUint64")
   466  	assertProperty(t, &sch, "string", "someFloat64", "double", "SomeFloat64")
   467  	assertProperty(t, &sch, "string", "someString", "", "SomeString")
   468  	assertProperty(t, &sch, "string", "someBool", "", "SomeBool")
   469  
   470  	prop, ok := sch.Properties["somethingElse"]
   471  	if assert.True(t, ok) {
   472  		assert.NotEqual(t, "string", prop.Type)
   473  	}
   474  }
   475  
   476  func TestIgnoredStructField(t *testing.T) {
   477  	sctx := loadClassificationPkgsCtx(t)
   478  	decl := getClassificationModel(sctx, "IgnoredFields")
   479  	require.NotNil(t, decl)
   480  	prs := &schemaBuilder{
   481  		ctx:  sctx,
   482  		decl: decl,
   483  	}
   484  	models := make(map[string]spec.Schema)
   485  	require.NoError(t, prs.Build(models))
   486  
   487  	sch := models["ignoredFields"]
   488  	assertProperty(t, &sch, "string", "someIncludedField", "", "SomeIncludedField")
   489  	assertProperty(t, &sch, "string", "someErroneouslyIncludedField", "", "SomeErroneouslyIncludedField")
   490  	assert.Len(t, sch.Properties, 2)
   491  }
   492  
   493  func TestParseStructFields(t *testing.T) {
   494  	sctx := loadClassificationPkgsCtx(t)
   495  	decl := getClassificationModel(sctx, "SimpleComplexModel")
   496  	require.NotNil(t, decl)
   497  	prs := &schemaBuilder{
   498  		ctx:  sctx,
   499  		decl: decl,
   500  	}
   501  	models := make(map[string]spec.Schema)
   502  	require.NoError(t, prs.Build(models))
   503  
   504  	schema := models["SimpleComplexModel"]
   505  	assertProperty(t, &schema, "object", "emb", "", "Emb")
   506  	eSchema := schema.Properties["emb"]
   507  	assertProperty(t, &eSchema, "integer", "cid", "int64", "CID")
   508  	assertProperty(t, &eSchema, "string", "baz", "", "Baz")
   509  
   510  	assertRef(t, &schema, "top", "Top", "#/definitions/Something")
   511  	assertRef(t, &schema, "notSel", "NotSel", "#/definitions/NotSelected")
   512  }
   513  
   514  func TestParsePointerFields(t *testing.T) {
   515  	sctx := loadClassificationPkgsCtx(t)
   516  	decl := getClassificationModel(sctx, "Pointdexter")
   517  	require.NotNil(t, decl)
   518  	prs := &schemaBuilder{
   519  		ctx:  sctx,
   520  		decl: decl,
   521  	}
   522  	models := make(map[string]spec.Schema)
   523  	require.NoError(t, prs.Build(models))
   524  
   525  	schema := models["Pointdexter"]
   526  
   527  	assertProperty(t, &schema, "integer", "id", "int64", "ID")
   528  	assertProperty(t, &schema, "string", "name", "", "Name")
   529  	assertProperty(t, &schema, "object", "emb", "", "Emb")
   530  	assertProperty(t, &schema, "string", "t", "uuid5", "T")
   531  	eSchema := schema.Properties["emb"]
   532  	assertProperty(t, &eSchema, "integer", "cid", "int64", "CID")
   533  	assertProperty(t, &eSchema, "string", "baz", "", "Baz")
   534  
   535  	assertRef(t, &schema, "top", "Top", "#/definitions/Something")
   536  	assertRef(t, &schema, "notSel", "NotSel", "#/definitions/NotSelected")
   537  }
   538  
   539  func TestEmbeddedStarExpr(t *testing.T) {
   540  	sctx := loadClassificationPkgsCtx(t)
   541  	decl := getClassificationModel(sctx, "EmbeddedStarExpr")
   542  	require.NotNil(t, decl)
   543  	prs := &schemaBuilder{
   544  		ctx:  sctx,
   545  		decl: decl,
   546  	}
   547  	models := make(map[string]spec.Schema)
   548  	require.NoError(t, prs.Build(models))
   549  
   550  	schema := models["EmbeddedStarExpr"]
   551  
   552  	assertProperty(t, &schema, "integer", "embeddedMember", "int64", "EmbeddedMember")
   553  	assertProperty(t, &schema, "integer", "notEmbedded", "int64", "NotEmbedded")
   554  }
   555  
   556  func TestArrayOfPointers(t *testing.T) {
   557  	sctx := loadClassificationPkgsCtx(t)
   558  	decl := getClassificationModel(sctx, "Cars")
   559  	require.NotNil(t, decl)
   560  	prs := &schemaBuilder{
   561  		ctx:  sctx,
   562  		decl: decl,
   563  	}
   564  	models := make(map[string]spec.Schema)
   565  	require.NoError(t, prs.Build(models))
   566  
   567  	schema := models["cars"]
   568  	assertProperty(t, &schema, "array", "cars", "", "Cars")
   569  }
   570  
   571  func TestOverridingOneIgnore(t *testing.T) {
   572  	sctx := loadClassificationPkgsCtx(t)
   573  	decl := getClassificationModel(sctx, "OverridingOneIgnore")
   574  	require.NotNil(t, decl)
   575  	prs := &schemaBuilder{
   576  		ctx:  sctx,
   577  		decl: decl,
   578  	}
   579  	models := make(map[string]spec.Schema)
   580  	require.NoError(t, prs.Build(models))
   581  
   582  	schema := models["OverridingOneIgnore"]
   583  
   584  	assertProperty(t, &schema, "integer", "id", "int64", "ID")
   585  	assertProperty(t, &schema, "string", "name", "", "Name")
   586  	assert.Len(t, schema.Properties, 2)
   587  }
   588  
   589  func TestParseSliceFields(t *testing.T) {
   590  	sctx := loadClassificationPkgsCtx(t)
   591  	decl := getClassificationModel(sctx, "SliceAndDice")
   592  	require.NotNil(t, decl)
   593  	prs := &schemaBuilder{
   594  		ctx:  sctx,
   595  		decl: decl,
   596  	}
   597  	models := make(map[string]spec.Schema)
   598  	require.NoError(t, prs.Build(models))
   599  
   600  	schema := models["SliceAndDice"]
   601  
   602  	assertArrayProperty(t, &schema, "integer", "ids", "int64", "IDs")
   603  	assertArrayProperty(t, &schema, "string", "names", "", "Names")
   604  	assertArrayProperty(t, &schema, "string", "uuids", "uuid", "UUIDs")
   605  	assertArrayProperty(t, &schema, "object", "embs", "", "Embs")
   606  	eSchema := schema.Properties["embs"].Items.Schema
   607  	assertArrayProperty(t, eSchema, "integer", "cid", "int64", "CID")
   608  	assertArrayProperty(t, eSchema, "string", "baz", "", "Baz")
   609  
   610  	assertArrayRef(t, &schema, "tops", "Tops", "#/definitions/Something")
   611  	assertArrayRef(t, &schema, "notSels", "NotSels", "#/definitions/NotSelected")
   612  
   613  	assertArrayProperty(t, &schema, "integer", "ptrIds", "int64", "PtrIDs")
   614  	assertArrayProperty(t, &schema, "string", "ptrNames", "", "PtrNames")
   615  	assertArrayProperty(t, &schema, "string", "ptrUuids", "uuid", "PtrUUIDs")
   616  	assertArrayProperty(t, &schema, "object", "ptrEmbs", "", "PtrEmbs")
   617  	eSchema = schema.Properties["ptrEmbs"].Items.Schema
   618  	assertArrayProperty(t, eSchema, "integer", "ptrCid", "int64", "PtrCID")
   619  	assertArrayProperty(t, eSchema, "string", "ptrBaz", "", "PtrBaz")
   620  
   621  	assertArrayRef(t, &schema, "ptrTops", "PtrTops", "#/definitions/Something")
   622  	assertArrayRef(t, &schema, "ptrNotSels", "PtrNotSels", "#/definitions/NotSelected")
   623  }
   624  
   625  func TestParseMapFields(t *testing.T) {
   626  	sctx := loadClassificationPkgsCtx(t)
   627  	decl := getClassificationModel(sctx, "MapTastic")
   628  	require.NotNil(t, decl)
   629  	prs := &schemaBuilder{
   630  		ctx:  sctx,
   631  		decl: decl,
   632  	}
   633  	models := make(map[string]spec.Schema)
   634  	require.NoError(t, prs.Build(models))
   635  
   636  	schema := models["MapTastic"]
   637  
   638  	assertMapProperty(t, &schema, "integer", "ids", "int64", "IDs")
   639  	assertMapProperty(t, &schema, "string", "names", "", "Names")
   640  	assertMapProperty(t, &schema, "string", "uuids", "uuid", "UUIDs")
   641  	assertMapProperty(t, &schema, "object", "embs", "", "Embs")
   642  	eSchema := schema.Properties["embs"].AdditionalProperties.Schema
   643  	assertMapProperty(t, eSchema, "integer", "cid", "int64", "CID")
   644  	assertMapProperty(t, eSchema, "string", "baz", "", "Baz")
   645  
   646  	assertMapRef(t, &schema, "tops", "Tops", "#/definitions/Something")
   647  	assertMapRef(t, &schema, "notSels", "NotSels", "#/definitions/NotSelected")
   648  
   649  	assertMapProperty(t, &schema, "integer", "ptrIds", "int64", "PtrIDs")
   650  	assertMapProperty(t, &schema, "string", "ptrNames", "", "PtrNames")
   651  	assertMapProperty(t, &schema, "string", "ptrUuids", "uuid", "PtrUUIDs")
   652  	assertMapProperty(t, &schema, "object", "ptrEmbs", "", "PtrEmbs")
   653  	eSchema = schema.Properties["ptrEmbs"].AdditionalProperties.Schema
   654  	assertMapProperty(t, eSchema, "integer", "ptrCid", "int64", "PtrCID")
   655  	assertMapProperty(t, eSchema, "string", "ptrBaz", "", "PtrBaz")
   656  
   657  	assertMapRef(t, &schema, "ptrTops", "PtrTops", "#/definitions/Something")
   658  	assertMapRef(t, &schema, "ptrNotSels", "PtrNotSels", "#/definitions/NotSelected")
   659  }
   660  
   661  func TestInterfaceField(t *testing.T) {
   662  	sctx := loadClassificationPkgsCtx(t)
   663  	decl := getClassificationModel(sctx, "Interfaced")
   664  	require.NotNil(t, decl)
   665  	prs := &schemaBuilder{
   666  		ctx:  sctx,
   667  		decl: decl,
   668  	}
   669  	models := make(map[string]spec.Schema)
   670  	require.NoError(t, prs.Build(models))
   671  
   672  	schema := models["Interfaced"]
   673  	assertProperty(t, &schema, "", "custom_data", "", "CustomData")
   674  }
   675  
   676  func TestAliasedTypes(t *testing.T) {
   677  	sctx := loadClassificationPkgsCtx(t)
   678  	decl := getClassificationModel(sctx, "OtherTypes")
   679  	require.NotNil(t, decl)
   680  	prs := &schemaBuilder{
   681  		ctx:  sctx,
   682  		decl: decl,
   683  	}
   684  	models := make(map[string]spec.Schema)
   685  	require.NoError(t, prs.Build(models))
   686  
   687  	schema := models["OtherTypes"]
   688  	assertRef(t, &schema, "named", "Named", "#/definitions/SomeStringType")
   689  	assertRef(t, &schema, "numbered", "Numbered", "#/definitions/SomeIntType")
   690  	assertProperty(t, &schema, "string", "dated", "date-time", "Dated")
   691  	assertRef(t, &schema, "timed", "Timed", "#/definitions/SomeTimedType")
   692  	assertRef(t, &schema, "petted", "Petted", "#/definitions/SomePettedType")
   693  	assertRef(t, &schema, "somethinged", "Somethinged", "#/definitions/SomethingType")
   694  	assertRef(t, &schema, "strMap", "StrMap", "#/definitions/SomeStringMap")
   695  	assertRef(t, &schema, "strArrMap", "StrArrMap", "#/definitions/SomeArrayStringMap")
   696  
   697  	assertRef(t, &schema, "manyNamed", "ManyNamed", "#/definitions/SomeStringsType")
   698  	assertRef(t, &schema, "manyNumbered", "ManyNumbered", "#/definitions/SomeIntsType")
   699  	assertArrayProperty(t, &schema, "string", "manyDated", "date-time", "ManyDated")
   700  	assertRef(t, &schema, "manyTimed", "ManyTimed", "#/definitions/SomeTimedsType")
   701  	assertRef(t, &schema, "manyPetted", "ManyPetted", "#/definitions/SomePettedsType")
   702  	assertRef(t, &schema, "manySomethinged", "ManySomethinged", "#/definitions/SomethingsType")
   703  
   704  	assertArrayRef(t, &schema, "nameds", "Nameds", "#/definitions/SomeStringType")
   705  	assertArrayRef(t, &schema, "numbereds", "Numbereds", "#/definitions/SomeIntType")
   706  	assertArrayProperty(t, &schema, "string", "dateds", "date-time", "Dateds")
   707  	assertArrayRef(t, &schema, "timeds", "Timeds", "#/definitions/SomeTimedType")
   708  	assertArrayRef(t, &schema, "petteds", "Petteds", "#/definitions/SomePettedType")
   709  	assertArrayRef(t, &schema, "somethingeds", "Somethingeds", "#/definitions/SomethingType")
   710  
   711  	assertRef(t, &schema, "modsNamed", "ModsNamed", "#/definitions/modsSomeStringType")
   712  	assertRef(t, &schema, "modsNumbered", "ModsNumbered", "#/definitions/modsSomeIntType")
   713  	assertProperty(t, &schema, "string", "modsDated", "date-time", "ModsDated")
   714  	assertRef(t, &schema, "modsTimed", "ModsTimed", "#/definitions/modsSomeTimedType")
   715  	assertRef(t, &schema, "modsPetted", "ModsPetted", "#/definitions/modsSomePettedType")
   716  
   717  	assertArrayRef(t, &schema, "modsNameds", "ModsNameds", "#/definitions/modsSomeStringType")
   718  	assertArrayRef(t, &schema, "modsNumbereds", "ModsNumbereds", "#/definitions/modsSomeIntType")
   719  	assertArrayProperty(t, &schema, "string", "modsDateds", "date-time", "ModsDateds")
   720  	assertArrayRef(t, &schema, "modsTimeds", "ModsTimeds", "#/definitions/modsSomeTimedType")
   721  	assertArrayRef(t, &schema, "modsPetteds", "ModsPetteds", "#/definitions/modsSomePettedType")
   722  
   723  	assertRef(t, &schema, "manyModsNamed", "ManyModsNamed", "#/definitions/modsSomeStringsType")
   724  	assertRef(t, &schema, "manyModsNumbered", "ManyModsNumbered", "#/definitions/modsSomeIntsType")
   725  	assertArrayProperty(t, &schema, "string", "manyModsDated", "date-time", "ManyModsDated")
   726  	assertRef(t, &schema, "manyModsTimed", "ManyModsTimed", "#/definitions/modsSomeTimedsType")
   727  	assertRef(t, &schema, "manyModsPetted", "ManyModsPetted", "#/definitions/modsSomePettedsType")
   728  	assertRef(t, &schema, "manyModsPettedPtr", "ManyModsPettedPtr", "#/definitions/modsSomePettedsPtrType")
   729  
   730  	assertProperty(t, &schema, "string", "namedAlias", "", "NamedAlias")
   731  	assertProperty(t, &schema, "integer", "numberedAlias", "int64", "NumberedAlias")
   732  	assertArrayProperty(t, &schema, "string", "namedsAlias", "", "NamedsAlias")
   733  	assertArrayProperty(t, &schema, "integer", "numberedsAlias", "int64", "NumberedsAlias")
   734  }
   735  
   736  func TestAliasedModels(t *testing.T) {
   737  	sctx := loadClassificationPkgsCtx(t)
   738  
   739  	names := []string{
   740  		"SomeStringType",
   741  		"SomeIntType",
   742  		"SomeTimeType",
   743  		"SomeTimedType",
   744  		"SomePettedType",
   745  		"SomethingType",
   746  		"SomeStringsType",
   747  		"SomeIntsType",
   748  		"SomeTimesType",
   749  		"SomeTimedsType",
   750  		"SomePettedsType",
   751  		"SomethingsType",
   752  		"SomeObject",
   753  		"SomeStringMap",
   754  		"SomeIntMap",
   755  		"SomeTimeMap",
   756  		"SomeTimedMap",
   757  		"SomePettedMap",
   758  		"SomeSomethingMap",
   759  	}
   760  
   761  	defs := make(map[string]spec.Schema)
   762  	for _, nm := range names {
   763  		decl := getClassificationModel(sctx, nm)
   764  		require.NotNil(t, decl)
   765  
   766  		prs := &schemaBuilder{
   767  			decl: decl,
   768  			ctx:  sctx,
   769  		}
   770  		require.NoError(t, prs.Build(defs))
   771  	}
   772  
   773  	for k := range defs {
   774  		for i, b := range names {
   775  			if b == k {
   776  				// remove the entry from the collection
   777  				names = append(names[:i], names[i+1:]...)
   778  			}
   779  		}
   780  	}
   781  	if assert.Empty(t, names) {
   782  		// single value types
   783  		assertDefinition(t, defs, "SomeStringType", "string", "", "")
   784  		assertDefinition(t, defs, "SomeIntType", "integer", "int64", "")
   785  		assertDefinition(t, defs, "SomeTimeType", "string", "date-time", "")
   786  		assertDefinition(t, defs, "SomeTimedType", "string", "date-time", "")
   787  		assertRefDefinition(t, defs, "SomePettedType", "#/definitions/pet", "")
   788  		assertRefDefinition(t, defs, "SomethingType", "#/definitions/Something", "")
   789  
   790  		// slice types
   791  		assertArrayDefinition(t, defs, "SomeStringsType", "string", "", "")
   792  		assertArrayDefinition(t, defs, "SomeIntsType", "integer", "int64", "")
   793  		assertArrayDefinition(t, defs, "SomeTimesType", "string", "date-time", "")
   794  		assertArrayDefinition(t, defs, "SomeTimedsType", "string", "date-time", "")
   795  		assertArrayWithRefDefinition(t, defs, "SomePettedsType", "#/definitions/pet", "")
   796  		assertArrayWithRefDefinition(t, defs, "SomethingsType", "#/definitions/Something", "")
   797  
   798  		// map types
   799  		assertMapDefinition(t, defs, "SomeObject", "object", "", "")
   800  		assertMapDefinition(t, defs, "SomeStringMap", "string", "", "")
   801  		assertMapDefinition(t, defs, "SomeIntMap", "integer", "int64", "")
   802  		assertMapDefinition(t, defs, "SomeTimeMap", "string", "date-time", "")
   803  		assertMapDefinition(t, defs, "SomeTimedMap", "string", "date-time", "")
   804  		assertMapWithRefDefinition(t, defs, "SomePettedMap", "#/definitions/pet", "")
   805  		assertMapWithRefDefinition(t, defs, "SomeSomethingMap", "#/definitions/Something", "")
   806  	}
   807  }
   808  
   809  func TestEmbeddedAllOf(t *testing.T) {
   810  	sctx := loadClassificationPkgsCtx(t)
   811  	decl := getClassificationModel(sctx, "AllOfModel")
   812  	require.NotNil(t, decl)
   813  	prs := &schemaBuilder{
   814  		ctx:  sctx,
   815  		decl: decl,
   816  	}
   817  	models := make(map[string]spec.Schema)
   818  	require.NoError(t, prs.Build(models))
   819  	schema := models["AllOfModel"]
   820  
   821  	require.Len(t, schema.AllOf, 3)
   822  	asch := schema.AllOf[0]
   823  	assertProperty(t, &asch, "integer", "age", "int32", "Age")
   824  	assertProperty(t, &asch, "integer", "id", "int64", "ID")
   825  	assertProperty(t, &asch, "string", "name", "", "Name")
   826  
   827  	asch = schema.AllOf[1]
   828  	assert.Equal(t, "#/definitions/withNotes", asch.Ref.String())
   829  
   830  	asch = schema.AllOf[2]
   831  	assertProperty(t, &asch, "string", "createdAt", "date-time", "CreatedAt")
   832  	assertProperty(t, &asch, "integer", "did", "int64", "DID")
   833  	assertProperty(t, &asch, "string", "cat", "", "Cat")
   834  }
   835  
   836  func TestSwaggerTypeNamed(t *testing.T) {
   837  	sctx := loadClassificationPkgsCtx(t)
   838  	decl := getClassificationModel(sctx, "NamedWithType")
   839  	require.NotNil(t, decl)
   840  	prs := &schemaBuilder{
   841  		ctx:  sctx,
   842  		decl: decl,
   843  	}
   844  	models := make(map[string]spec.Schema)
   845  	require.NoError(t, prs.Build(models))
   846  	schema := models["namedWithType"]
   847  
   848  	assertProperty(t, &schema, "object", "some_map", "", "SomeMap")
   849  }
   850  
   851  func TestSwaggerTypeStruct(t *testing.T) {
   852  	sctx := loadClassificationPkgsCtx(t)
   853  	decl := getClassificationModel(sctx, "NullString")
   854  	require.NotNil(t, decl)
   855  	prs := &schemaBuilder{
   856  		ctx:  sctx,
   857  		decl: decl,
   858  	}
   859  	models := make(map[string]spec.Schema)
   860  	require.NoError(t, prs.Build(models))
   861  	schema := models["NullString"]
   862  
   863  	assert.True(t, schema.Type.Contains("string"))
   864  }
   865  
   866  func TestStructDiscriminators(t *testing.T) {
   867  	sctx := loadClassificationPkgsCtx(t)
   868  
   869  	models := make(map[string]spec.Schema)
   870  	for _, tn := range []string{"BaseStruct", "Giraffe", "Gazelle"} {
   871  		decl := getClassificationModel(sctx, tn)
   872  		require.NotNil(t, decl)
   873  		prs := &schemaBuilder{
   874  			ctx:  sctx,
   875  			decl: decl,
   876  		}
   877  		require.NoError(t, prs.Build(models))
   878  	}
   879  
   880  	schema := models["animal"]
   881  
   882  	assert.Equal(t, "BaseStruct", schema.Extensions["x-go-name"])
   883  	assert.Equal(t, "jsonClass", schema.Discriminator)
   884  
   885  	sch := models["gazelle"]
   886  	assert.Len(t, sch.AllOf, 2)
   887  	cl, _ := sch.Extensions.GetString("x-class")
   888  	assert.Equal(t, "a.b.c.d.E", cl)
   889  	cl, _ = sch.Extensions.GetString("x-go-name")
   890  	assert.Equal(t, "Gazelle", cl)
   891  
   892  	sch = models["giraffe"]
   893  	assert.Len(t, sch.AllOf, 2)
   894  	cl, _ = sch.Extensions.GetString("x-class")
   895  	assert.Equal(t, "", cl)
   896  	cl, _ = sch.Extensions.GetString("x-go-name")
   897  	assert.Equal(t, "Giraffe", cl)
   898  
   899  	// sch = noModelDefs["lion"]
   900  
   901  	// b, _ := json.MarshalIndent(sch, "", "  ")
   902  	// fmt.Println(string(b))
   903  }
   904  
   905  func TestInterfaceDiscriminators(t *testing.T) {
   906  	sctx := loadClassificationPkgsCtx(t)
   907  	models := make(map[string]spec.Schema)
   908  	for _, tn := range []string{"BaseStruct", "Identifiable", "WaterType", "Fish", "TeslaCar", "ModelS", "ModelX", "ModelA", "Cars"} {
   909  		decl := getClassificationModel(sctx, tn)
   910  		require.NotNil(t, decl)
   911  
   912  		prs := &schemaBuilder{
   913  			ctx:  sctx,
   914  			decl: decl,
   915  		}
   916  		require.NoError(t, prs.Build(models))
   917  	}
   918  
   919  	schema, ok := models["fish"]
   920  
   921  	if assert.True(t, ok) && assert.Len(t, schema.AllOf, 5) {
   922  		sch := schema.AllOf[3]
   923  		assert.Len(t, sch.Properties, 1)
   924  		assertProperty(t, &sch, "string", "colorName", "", "ColorName")
   925  
   926  		sch = schema.AllOf[2]
   927  		assert.Equal(t, "#/definitions/extra", sch.Ref.String())
   928  
   929  		sch = schema.AllOf[0]
   930  		assert.Len(t, sch.Properties, 1)
   931  		assertProperty(t, &sch, "integer", "id", "int64", "ID")
   932  
   933  		sch = schema.AllOf[1]
   934  		assert.Equal(t, "#/definitions/water", sch.Ref.String())
   935  
   936  		sch = schema.AllOf[4]
   937  		assert.Len(t, sch.Properties, 2)
   938  		assertProperty(t, &sch, "string", "name", "", "Name")
   939  		assertProperty(t, &sch, "string", "jsonClass", "", "StructType")
   940  		assert.Equal(t, "jsonClass", sch.Discriminator)
   941  	}
   942  
   943  	schema, ok = models["modelS"]
   944  	if assert.True(t, ok) {
   945  		assert.Len(t, schema.AllOf, 2)
   946  		cl, _ := schema.Extensions.GetString("x-class")
   947  		assert.Equal(t, "com.tesla.models.ModelS", cl)
   948  		cl, _ = schema.Extensions.GetString("x-go-name")
   949  		assert.Equal(t, "ModelS", cl)
   950  
   951  		sch := schema.AllOf[0]
   952  		assert.Equal(t, "#/definitions/TeslaCar", sch.Ref.String())
   953  		sch = schema.AllOf[1]
   954  		assert.Len(t, sch.Properties, 1)
   955  		assertProperty(t, &sch, "string", "edition", "", "Edition")
   956  	}
   957  
   958  	schema, ok = models["modelA"]
   959  	if assert.True(t, ok) {
   960  
   961  		cl, _ := schema.Extensions.GetString("x-go-name")
   962  		assert.Equal(t, "ModelA", cl)
   963  
   964  		sch, ok := schema.Properties["Tesla"]
   965  		if assert.True(t, ok) {
   966  			assert.Equal(t, "#/definitions/TeslaCar", sch.Ref.String())
   967  		}
   968  
   969  		assertProperty(t, &schema, "integer", "doors", "int64", "Doors")
   970  	}
   971  }
   972  
   973  func TestAddExtension(t *testing.T) {
   974  	ve := &spec.VendorExtensible{
   975  		Extensions: make(spec.Extensions),
   976  	}
   977  
   978  	key := "x-go-name"
   979  	value := "Name"
   980  	addExtension(ve, key, value)
   981  	assert.Equal(t, value, ve.Extensions[key].(string))
   982  
   983  	key2 := "x-go-package"
   984  	value2 := "schema"
   985  	_ = os.Setenv("SWAGGER_GENERATE_EXTENSION", "true")
   986  	addExtension(ve, key2, value2)
   987  	assert.Equal(t, value2, ve.Extensions[key2].(string))
   988  
   989  	key3 := "x-go-class"
   990  	value3 := "Spec"
   991  	_ = os.Setenv("SWAGGER_GENERATE_EXTENSION", "false")
   992  	addExtension(ve, key3, value3)
   993  	assert.Nil(t, ve.Extensions[key3])
   994  }
   995  
   996  func getClassificationModel(sctx *scanCtx, nm string) *entityDecl {
   997  	decl, ok := sctx.FindDecl("github.com/go-swagger/go-swagger/fixtures/goparsing/classification/models", nm)
   998  	if !ok {
   999  		return nil
  1000  	}
  1001  	return decl
  1002  }
  1003  
  1004  func assertArrayProperty(t testing.TB, schema *spec.Schema, typeName, jsonName, format, goName string) {
  1005  	prop := schema.Properties[jsonName]
  1006  	assert.NotEmpty(t, prop.Type)
  1007  	assert.True(t, prop.Type.Contains("array"))
  1008  	assert.NotNil(t, prop.Items)
  1009  	if typeName != "" {
  1010  		assert.Equal(t, typeName, prop.Items.Schema.Type[0])
  1011  	}
  1012  	assert.Equal(t, goName, prop.Extensions["x-go-name"])
  1013  	assert.Equal(t, format, prop.Items.Schema.Format)
  1014  }
  1015  
  1016  func assertArrayRef(t testing.TB, schema *spec.Schema, jsonName, goName, fragment string) {
  1017  	assertArrayProperty(t, schema, "", jsonName, "", goName)
  1018  	psch := schema.Properties[jsonName].Items.Schema
  1019  	assert.Equal(t, fragment, psch.Ref.String())
  1020  }
  1021  
  1022  func assertProperty(t testing.TB, schema *spec.Schema, typeName, jsonName, format, goName string) {
  1023  	if typeName == "" {
  1024  		assert.Empty(t, schema.Properties[jsonName].Type)
  1025  	} else if assert.NotEmpty(t, schema.Properties[jsonName].Type) {
  1026  		assert.Equal(t, typeName, schema.Properties[jsonName].Type[0])
  1027  	}
  1028  	if goName == "" {
  1029  		assert.Nil(t, schema.Properties[jsonName].Extensions["x-go-name"])
  1030  	} else {
  1031  		assert.Equal(t, goName, schema.Properties[jsonName].Extensions["x-go-name"])
  1032  	}
  1033  	assert.Equal(t, format, schema.Properties[jsonName].Format)
  1034  }
  1035  
  1036  func assertRef(t testing.TB, schema *spec.Schema, jsonName, _, fragment string) {
  1037  	assert.Empty(t, schema.Properties[jsonName].Type)
  1038  	psch := schema.Properties[jsonName]
  1039  	assert.Equal(t, fragment, psch.Ref.String())
  1040  }
  1041  
  1042  func assertDefinition(t testing.TB, defs map[string]spec.Schema, defName, typeName, formatName, goName string) {
  1043  	schema, ok := defs[defName]
  1044  	if assert.True(t, ok) {
  1045  		if assert.NotEmpty(t, schema.Type) {
  1046  			assert.Equal(t, typeName, schema.Type[0])
  1047  			if goName != "" {
  1048  				assert.Equal(t, goName, schema.Extensions["x-go-name"])
  1049  			} else {
  1050  				assert.Nil(t, schema.Extensions["x-go-name"])
  1051  			}
  1052  			assert.Equal(t, formatName, schema.Format)
  1053  		}
  1054  	}
  1055  }
  1056  
  1057  func assertMapDefinition(t testing.TB, defs map[string]spec.Schema, defName, typeName, formatName, goName string) {
  1058  	schema, ok := defs[defName]
  1059  	if assert.True(t, ok) {
  1060  		if assert.NotEmpty(t, schema.Type) {
  1061  			assert.Equal(t, "object", schema.Type[0])
  1062  			adl := schema.AdditionalProperties
  1063  			if assert.NotNil(t, adl) && assert.NotNil(t, adl.Schema) {
  1064  				if len(adl.Schema.Type) > 0 {
  1065  					assert.Equal(t, typeName, adl.Schema.Type[0])
  1066  				}
  1067  				assert.Equal(t, formatName, adl.Schema.Format)
  1068  			}
  1069  			if goName != "" {
  1070  				assert.Equal(t, goName, schema.Extensions["x-go-name"])
  1071  			} else {
  1072  				assert.Nil(t, schema.Extensions["x-go-name"])
  1073  			}
  1074  		}
  1075  	}
  1076  }
  1077  
  1078  func assertMapWithRefDefinition(t testing.TB, defs map[string]spec.Schema, defName, refURL, goName string) {
  1079  	schema, ok := defs[defName]
  1080  	if assert.True(t, ok) {
  1081  		if assert.NotEmpty(t, schema.Type) {
  1082  			assert.Equal(t, "object", schema.Type[0])
  1083  			adl := schema.AdditionalProperties
  1084  			if assert.NotNil(t, adl) && assert.NotNil(t, adl.Schema) {
  1085  				if assert.NotZero(t, adl.Schema.Ref) {
  1086  					assert.Equal(t, refURL, adl.Schema.Ref.String())
  1087  				}
  1088  			}
  1089  			if goName != "" {
  1090  				assert.Equal(t, goName, schema.Extensions["x-go-name"])
  1091  			} else {
  1092  				assert.Nil(t, schema.Extensions["x-go-name"])
  1093  			}
  1094  		}
  1095  	}
  1096  }
  1097  
  1098  func assertArrayDefinition(t testing.TB, defs map[string]spec.Schema, defName, typeName, formatName, goName string) {
  1099  	schema, ok := defs[defName]
  1100  	if assert.True(t, ok) {
  1101  		if assert.NotEmpty(t, schema.Type) {
  1102  			assert.Equal(t, "array", schema.Type[0])
  1103  			adl := schema.Items
  1104  			if assert.NotNil(t, adl) && assert.NotNil(t, adl.Schema) {
  1105  				assert.Equal(t, typeName, adl.Schema.Type[0])
  1106  				assert.Equal(t, formatName, adl.Schema.Format)
  1107  			}
  1108  			if goName != "" {
  1109  				assert.Equal(t, goName, schema.Extensions["x-go-name"])
  1110  			} else {
  1111  				assert.Nil(t, schema.Extensions["x-go-name"])
  1112  			}
  1113  		}
  1114  	}
  1115  }
  1116  
  1117  func assertArrayWithRefDefinition(t testing.TB, defs map[string]spec.Schema, defName, refURL, goName string) {
  1118  	schema, ok := defs[defName]
  1119  	if assert.True(t, ok) {
  1120  		if assert.NotEmpty(t, schema.Type) {
  1121  			assert.Equal(t, "array", schema.Type[0])
  1122  			adl := schema.Items
  1123  			if assert.NotNil(t, adl) && assert.NotNil(t, adl.Schema) {
  1124  				if assert.NotZero(t, adl.Schema.Ref) {
  1125  					assert.Equal(t, refURL, adl.Schema.Ref.String())
  1126  				}
  1127  			}
  1128  			if goName != "" {
  1129  				assert.Equal(t, goName, schema.Extensions["x-go-name"])
  1130  			} else {
  1131  				assert.Nil(t, schema.Extensions["x-go-name"])
  1132  			}
  1133  		}
  1134  	}
  1135  }
  1136  
  1137  func assertRefDefinition(t testing.TB, defs map[string]spec.Schema, defName, refURL, goName string) {
  1138  	schema, ok := defs[defName]
  1139  	if assert.True(t, ok) {
  1140  		if assert.NotZero(t, schema.Ref) {
  1141  			url := schema.Ref.String()
  1142  			assert.Equal(t, refURL, url)
  1143  			if goName != "" {
  1144  				assert.Equal(t, goName, schema.Extensions["x-go-name"])
  1145  			} else {
  1146  				assert.Nil(t, schema.Extensions["x-go-name"])
  1147  			}
  1148  		}
  1149  	}
  1150  }
  1151  
  1152  func assertMapProperty(t testing.TB, schema *spec.Schema, typeName, jsonName, format, goName string) {
  1153  	prop := schema.Properties[jsonName]
  1154  	assert.NotEmpty(t, prop.Type)
  1155  	assert.True(t, prop.Type.Contains("object"))
  1156  	assert.NotNil(t, prop.AdditionalProperties)
  1157  	if typeName != "" {
  1158  		assert.Equal(t, typeName, prop.AdditionalProperties.Schema.Type[0])
  1159  	}
  1160  	assert.Equal(t, goName, prop.Extensions["x-go-name"])
  1161  	assert.Equal(t, format, prop.AdditionalProperties.Schema.Format)
  1162  }
  1163  
  1164  func assertMapRef(t testing.TB, schema *spec.Schema, jsonName, goName, fragment string) {
  1165  	assertMapProperty(t, schema, "", jsonName, "", goName)
  1166  	psch := schema.Properties[jsonName].AdditionalProperties.Schema
  1167  	assert.Equal(t, fragment, psch.Ref.String())
  1168  }