github.com/AngusLu/go-swagger@v0.28.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/AngusLu/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/AngusLu/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  }
   301  
   302  func TestEmbeddedTypes(t *testing.T) {
   303  	sctx := loadClassificationPkgsCtx(t)
   304  	decl := getClassificationModel(sctx, "ComplexerOne")
   305  	require.NotNil(t, decl)
   306  	prs := &schemaBuilder{
   307  		ctx:  sctx,
   308  		decl: decl,
   309  	}
   310  	models := make(map[string]spec.Schema)
   311  	require.NoError(t, prs.Build(models))
   312  	schema := models["ComplexerOne"]
   313  	assertProperty(t, &schema, "integer", "age", "int32", "Age")
   314  	assertProperty(t, &schema, "integer", "id", "int64", "ID")
   315  	assertProperty(t, &schema, "string", "createdAt", "date-time", "CreatedAt")
   316  	assertProperty(t, &schema, "string", "extra", "", "Extra")
   317  	assertProperty(t, &schema, "string", "name", "", "Name")
   318  	assertProperty(t, &schema, "string", "notes", "", "Notes")
   319  }
   320  
   321  func TestParsePrimitiveSchemaProperty(t *testing.T) {
   322  	sctx := loadClassificationPkgsCtx(t)
   323  	decl := getClassificationModel(sctx, "PrimateModel")
   324  	require.NotNil(t, decl)
   325  	prs := &schemaBuilder{
   326  		ctx:  sctx,
   327  		decl: decl,
   328  	}
   329  	models := make(map[string]spec.Schema)
   330  	require.NoError(t, prs.Build(models))
   331  
   332  	schema := models["PrimateModel"]
   333  	assertProperty(t, &schema, "boolean", "a", "", "A")
   334  	assertProperty(t, &schema, "integer", "b", "int32", "B")
   335  	assertProperty(t, &schema, "string", "c", "", "C")
   336  	assertProperty(t, &schema, "integer", "d", "int64", "D")
   337  	assertProperty(t, &schema, "integer", "e", "int8", "E")
   338  	assertProperty(t, &schema, "integer", "f", "int16", "F")
   339  	assertProperty(t, &schema, "integer", "g", "int32", "G")
   340  	assertProperty(t, &schema, "integer", "h", "int64", "H")
   341  	assertProperty(t, &schema, "integer", "i", "uint64", "I")
   342  	assertProperty(t, &schema, "integer", "j", "uint8", "J")
   343  	assertProperty(t, &schema, "integer", "k", "uint16", "K")
   344  	assertProperty(t, &schema, "integer", "l", "uint32", "L")
   345  	assertProperty(t, &schema, "integer", "m", "uint64", "M")
   346  	assertProperty(t, &schema, "number", "n", "float", "N")
   347  	assertProperty(t, &schema, "number", "o", "double", "O")
   348  	assertProperty(t, &schema, "integer", "p", "uint8", "P")
   349  	assertProperty(t, &schema, "integer", "q", "uint64", "Q")
   350  }
   351  
   352  func TestParseStringFormatSchemaProperty(t *testing.T) {
   353  	sctx := loadClassificationPkgsCtx(t)
   354  	decl := getClassificationModel(sctx, "FormattedModel")
   355  	require.NotNil(t, decl)
   356  	prs := &schemaBuilder{
   357  		ctx:  sctx,
   358  		decl: decl,
   359  	}
   360  	models := make(map[string]spec.Schema)
   361  	require.NoError(t, prs.Build(models))
   362  
   363  	schema := models["FormattedModel"]
   364  	assertProperty(t, &schema, "string", "a", "byte", "A")
   365  	assertProperty(t, &schema, "string", "b", "creditcard", "B")
   366  	assertProperty(t, &schema, "string", "c", "date", "C")
   367  	assertProperty(t, &schema, "string", "d", "date-time", "D")
   368  	assertProperty(t, &schema, "string", "e", "duration", "E")
   369  	assertProperty(t, &schema, "string", "f", "email", "F")
   370  	assertProperty(t, &schema, "string", "g", "hexcolor", "G")
   371  	assertProperty(t, &schema, "string", "h", "hostname", "H")
   372  	assertProperty(t, &schema, "string", "i", "ipv4", "I")
   373  	assertProperty(t, &schema, "string", "j", "ipv6", "J")
   374  	assertProperty(t, &schema, "string", "k", "isbn", "K")
   375  	assertProperty(t, &schema, "string", "l", "isbn10", "L")
   376  	assertProperty(t, &schema, "string", "m", "isbn13", "M")
   377  	assertProperty(t, &schema, "string", "n", "rgbcolor", "N")
   378  	assertProperty(t, &schema, "string", "o", "ssn", "O")
   379  	assertProperty(t, &schema, "string", "p", "uri", "P")
   380  	assertProperty(t, &schema, "string", "q", "uuid", "Q")
   381  	assertProperty(t, &schema, "string", "r", "uuid3", "R")
   382  	assertProperty(t, &schema, "string", "s", "uuid4", "S")
   383  	assertProperty(t, &schema, "string", "t", "uuid5", "T")
   384  	assertProperty(t, &schema, "string", "u", "mac", "U")
   385  }
   386  
   387  func TestStringStructTag(t *testing.T) {
   388  	sctx := loadClassificationPkgsCtx(t)
   389  	decl := getClassificationModel(sctx, "JSONString")
   390  	require.NotNil(t, decl)
   391  	prs := &schemaBuilder{
   392  		ctx:  sctx,
   393  		decl: decl,
   394  	}
   395  	models := make(map[string]spec.Schema)
   396  	require.NoError(t, prs.Build(models))
   397  
   398  	sch := models["jsonString"]
   399  	assertProperty(t, &sch, "string", "someInt", "int64", "SomeInt")
   400  	assertProperty(t, &sch, "string", "someInt8", "int8", "SomeInt8")
   401  	assertProperty(t, &sch, "string", "someInt16", "int16", "SomeInt16")
   402  	assertProperty(t, &sch, "string", "someInt32", "int32", "SomeInt32")
   403  	assertProperty(t, &sch, "string", "someInt64", "int64", "SomeInt64")
   404  	assertProperty(t, &sch, "string", "someUint", "uint64", "SomeUint")
   405  	assertProperty(t, &sch, "string", "someUint8", "uint8", "SomeUint8")
   406  	assertProperty(t, &sch, "string", "someUint16", "uint16", "SomeUint16")
   407  	assertProperty(t, &sch, "string", "someUint32", "uint32", "SomeUint32")
   408  	assertProperty(t, &sch, "string", "someUint64", "uint64", "SomeUint64")
   409  	assertProperty(t, &sch, "string", "someFloat64", "double", "SomeFloat64")
   410  	assertProperty(t, &sch, "string", "someString", "", "SomeString")
   411  	assertProperty(t, &sch, "string", "someBool", "", "SomeBool")
   412  	assertProperty(t, &sch, "string", "SomeDefaultInt", "int64", "")
   413  
   414  	prop, ok := sch.Properties["somethingElse"]
   415  	if assert.True(t, ok) {
   416  		assert.NotEqual(t, "string", prop.Type)
   417  	}
   418  }
   419  
   420  func TestPtrFieldStringStructTag(t *testing.T) {
   421  	sctx := loadClassificationPkgsCtx(t)
   422  	decl := getClassificationModel(sctx, "JSONPtrString")
   423  	require.NotNil(t, decl)
   424  	prs := &schemaBuilder{
   425  		ctx:  sctx,
   426  		decl: decl,
   427  	}
   428  	models := make(map[string]spec.Schema)
   429  	require.NoError(t, prs.Build(models))
   430  
   431  	sch := models["jsonPtrString"]
   432  	assertProperty(t, &sch, "string", "someInt", "int64", "SomeInt")
   433  	assertProperty(t, &sch, "string", "someInt8", "int8", "SomeInt8")
   434  	assertProperty(t, &sch, "string", "someInt16", "int16", "SomeInt16")
   435  	assertProperty(t, &sch, "string", "someInt32", "int32", "SomeInt32")
   436  	assertProperty(t, &sch, "string", "someInt64", "int64", "SomeInt64")
   437  	assertProperty(t, &sch, "string", "someUint", "uint64", "SomeUint")
   438  	assertProperty(t, &sch, "string", "someUint8", "uint8", "SomeUint8")
   439  	assertProperty(t, &sch, "string", "someUint16", "uint16", "SomeUint16")
   440  	assertProperty(t, &sch, "string", "someUint32", "uint32", "SomeUint32")
   441  	assertProperty(t, &sch, "string", "someUint64", "uint64", "SomeUint64")
   442  	assertProperty(t, &sch, "string", "someFloat64", "double", "SomeFloat64")
   443  	assertProperty(t, &sch, "string", "someString", "", "SomeString")
   444  	assertProperty(t, &sch, "string", "someBool", "", "SomeBool")
   445  
   446  	prop, ok := sch.Properties["somethingElse"]
   447  	if assert.True(t, ok) {
   448  		assert.NotEqual(t, "string", prop.Type)
   449  	}
   450  }
   451  
   452  func TestIgnoredStructField(t *testing.T) {
   453  	sctx := loadClassificationPkgsCtx(t)
   454  	decl := getClassificationModel(sctx, "IgnoredFields")
   455  	require.NotNil(t, decl)
   456  	prs := &schemaBuilder{
   457  		ctx:  sctx,
   458  		decl: decl,
   459  	}
   460  	models := make(map[string]spec.Schema)
   461  	require.NoError(t, prs.Build(models))
   462  
   463  	sch := models["ignoredFields"]
   464  	assertProperty(t, &sch, "string", "someIncludedField", "", "SomeIncludedField")
   465  	assertProperty(t, &sch, "string", "someErroneouslyIncludedField", "", "SomeErroneouslyIncludedField")
   466  	assert.Len(t, sch.Properties, 2)
   467  }
   468  
   469  func TestParseStructFields(t *testing.T) {
   470  	sctx := loadClassificationPkgsCtx(t)
   471  	decl := getClassificationModel(sctx, "SimpleComplexModel")
   472  	require.NotNil(t, decl)
   473  	prs := &schemaBuilder{
   474  		ctx:  sctx,
   475  		decl: decl,
   476  	}
   477  	models := make(map[string]spec.Schema)
   478  	require.NoError(t, prs.Build(models))
   479  
   480  	schema := models["SimpleComplexModel"]
   481  	assertProperty(t, &schema, "object", "emb", "", "Emb")
   482  	eSchema := schema.Properties["emb"]
   483  	assertProperty(t, &eSchema, "integer", "cid", "int64", "CID")
   484  	assertProperty(t, &eSchema, "string", "baz", "", "Baz")
   485  
   486  	assertRef(t, &schema, "top", "Top", "#/definitions/Something")
   487  	assertRef(t, &schema, "notSel", "NotSel", "#/definitions/NotSelected")
   488  }
   489  
   490  func TestParsePointerFields(t *testing.T) {
   491  	sctx := loadClassificationPkgsCtx(t)
   492  	decl := getClassificationModel(sctx, "Pointdexter")
   493  	require.NotNil(t, decl)
   494  	prs := &schemaBuilder{
   495  		ctx:  sctx,
   496  		decl: decl,
   497  	}
   498  	models := make(map[string]spec.Schema)
   499  	require.NoError(t, prs.Build(models))
   500  
   501  	schema := models["Pointdexter"]
   502  
   503  	assertProperty(t, &schema, "integer", "id", "int64", "ID")
   504  	assertProperty(t, &schema, "string", "name", "", "Name")
   505  	assertProperty(t, &schema, "object", "emb", "", "Emb")
   506  	assertProperty(t, &schema, "string", "t", "uuid5", "T")
   507  	eSchema := schema.Properties["emb"]
   508  	assertProperty(t, &eSchema, "integer", "cid", "int64", "CID")
   509  	assertProperty(t, &eSchema, "string", "baz", "", "Baz")
   510  
   511  	assertRef(t, &schema, "top", "Top", "#/definitions/Something")
   512  	assertRef(t, &schema, "notSel", "NotSel", "#/definitions/NotSelected")
   513  }
   514  
   515  func TestEmbeddedStarExpr(t *testing.T) {
   516  	sctx := loadClassificationPkgsCtx(t)
   517  	decl := getClassificationModel(sctx, "EmbeddedStarExpr")
   518  	require.NotNil(t, decl)
   519  	prs := &schemaBuilder{
   520  		ctx:  sctx,
   521  		decl: decl,
   522  	}
   523  	models := make(map[string]spec.Schema)
   524  	require.NoError(t, prs.Build(models))
   525  
   526  	schema := models["EmbeddedStarExpr"]
   527  
   528  	assertProperty(t, &schema, "integer", "embeddedMember", "int64", "EmbeddedMember")
   529  	assertProperty(t, &schema, "integer", "notEmbedded", "int64", "NotEmbedded")
   530  }
   531  
   532  func TestArrayOfPointers(t *testing.T) {
   533  	sctx := loadClassificationPkgsCtx(t)
   534  	decl := getClassificationModel(sctx, "Cars")
   535  	require.NotNil(t, decl)
   536  	prs := &schemaBuilder{
   537  		ctx:  sctx,
   538  		decl: decl,
   539  	}
   540  	models := make(map[string]spec.Schema)
   541  	require.NoError(t, prs.Build(models))
   542  
   543  	schema := models["cars"]
   544  	assertProperty(t, &schema, "array", "cars", "", "Cars")
   545  }
   546  
   547  func TestOverridingOneIgnore(t *testing.T) {
   548  	sctx := loadClassificationPkgsCtx(t)
   549  	decl := getClassificationModel(sctx, "OverridingOneIgnore")
   550  	require.NotNil(t, decl)
   551  	prs := &schemaBuilder{
   552  		ctx:  sctx,
   553  		decl: decl,
   554  	}
   555  	models := make(map[string]spec.Schema)
   556  	require.NoError(t, prs.Build(models))
   557  
   558  	schema := models["OverridingOneIgnore"]
   559  
   560  	assertProperty(t, &schema, "integer", "id", "int64", "ID")
   561  	assertProperty(t, &schema, "string", "name", "", "Name")
   562  	assert.Len(t, schema.Properties, 2)
   563  }
   564  
   565  func TestParseSliceFields(t *testing.T) {
   566  	sctx := loadClassificationPkgsCtx(t)
   567  	decl := getClassificationModel(sctx, "SliceAndDice")
   568  	require.NotNil(t, decl)
   569  	prs := &schemaBuilder{
   570  		ctx:  sctx,
   571  		decl: decl,
   572  	}
   573  	models := make(map[string]spec.Schema)
   574  	require.NoError(t, prs.Build(models))
   575  
   576  	schema := models["SliceAndDice"]
   577  
   578  	assertArrayProperty(t, &schema, "integer", "ids", "int64", "IDs")
   579  	assertArrayProperty(t, &schema, "string", "names", "", "Names")
   580  	assertArrayProperty(t, &schema, "string", "uuids", "uuid", "UUIDs")
   581  	assertArrayProperty(t, &schema, "object", "embs", "", "Embs")
   582  	eSchema := schema.Properties["embs"].Items.Schema
   583  	assertArrayProperty(t, eSchema, "integer", "cid", "int64", "CID")
   584  	assertArrayProperty(t, eSchema, "string", "baz", "", "Baz")
   585  
   586  	assertArrayRef(t, &schema, "tops", "Tops", "#/definitions/Something")
   587  	assertArrayRef(t, &schema, "notSels", "NotSels", "#/definitions/NotSelected")
   588  
   589  	assertArrayProperty(t, &schema, "integer", "ptrIds", "int64", "PtrIDs")
   590  	assertArrayProperty(t, &schema, "string", "ptrNames", "", "PtrNames")
   591  	assertArrayProperty(t, &schema, "string", "ptrUuids", "uuid", "PtrUUIDs")
   592  	assertArrayProperty(t, &schema, "object", "ptrEmbs", "", "PtrEmbs")
   593  	eSchema = schema.Properties["ptrEmbs"].Items.Schema
   594  	assertArrayProperty(t, eSchema, "integer", "ptrCid", "int64", "PtrCID")
   595  	assertArrayProperty(t, eSchema, "string", "ptrBaz", "", "PtrBaz")
   596  
   597  	assertArrayRef(t, &schema, "ptrTops", "PtrTops", "#/definitions/Something")
   598  	assertArrayRef(t, &schema, "ptrNotSels", "PtrNotSels", "#/definitions/NotSelected")
   599  }
   600  
   601  func TestParseMapFields(t *testing.T) {
   602  	sctx := loadClassificationPkgsCtx(t)
   603  	decl := getClassificationModel(sctx, "MapTastic")
   604  	require.NotNil(t, decl)
   605  	prs := &schemaBuilder{
   606  		ctx:  sctx,
   607  		decl: decl,
   608  	}
   609  	models := make(map[string]spec.Schema)
   610  	require.NoError(t, prs.Build(models))
   611  
   612  	schema := models["MapTastic"]
   613  
   614  	assertMapProperty(t, &schema, "integer", "ids", "int64", "IDs")
   615  	assertMapProperty(t, &schema, "string", "names", "", "Names")
   616  	assertMapProperty(t, &schema, "string", "uuids", "uuid", "UUIDs")
   617  	assertMapProperty(t, &schema, "object", "embs", "", "Embs")
   618  	eSchema := schema.Properties["embs"].AdditionalProperties.Schema
   619  	assertMapProperty(t, eSchema, "integer", "cid", "int64", "CID")
   620  	assertMapProperty(t, eSchema, "string", "baz", "", "Baz")
   621  
   622  	assertMapRef(t, &schema, "tops", "Tops", "#/definitions/Something")
   623  	assertMapRef(t, &schema, "notSels", "NotSels", "#/definitions/NotSelected")
   624  
   625  	assertMapProperty(t, &schema, "integer", "ptrIds", "int64", "PtrIDs")
   626  	assertMapProperty(t, &schema, "string", "ptrNames", "", "PtrNames")
   627  	assertMapProperty(t, &schema, "string", "ptrUuids", "uuid", "PtrUUIDs")
   628  	assertMapProperty(t, &schema, "object", "ptrEmbs", "", "PtrEmbs")
   629  	eSchema = schema.Properties["ptrEmbs"].AdditionalProperties.Schema
   630  	assertMapProperty(t, eSchema, "integer", "ptrCid", "int64", "PtrCID")
   631  	assertMapProperty(t, eSchema, "string", "ptrBaz", "", "PtrBaz")
   632  
   633  	assertMapRef(t, &schema, "ptrTops", "PtrTops", "#/definitions/Something")
   634  	assertMapRef(t, &schema, "ptrNotSels", "PtrNotSels", "#/definitions/NotSelected")
   635  }
   636  
   637  func TestInterfaceField(t *testing.T) {
   638  	sctx := loadClassificationPkgsCtx(t)
   639  	decl := getClassificationModel(sctx, "Interfaced")
   640  	require.NotNil(t, decl)
   641  	prs := &schemaBuilder{
   642  		ctx:  sctx,
   643  		decl: decl,
   644  	}
   645  	models := make(map[string]spec.Schema)
   646  	require.NoError(t, prs.Build(models))
   647  
   648  	schema := models["Interfaced"]
   649  	assertProperty(t, &schema, "object", "custom_data", "", "CustomData")
   650  }
   651  
   652  func TestAliasedTypes(t *testing.T) {
   653  	sctx := loadClassificationPkgsCtx(t)
   654  	decl := getClassificationModel(sctx, "OtherTypes")
   655  	require.NotNil(t, decl)
   656  	prs := &schemaBuilder{
   657  		ctx:  sctx,
   658  		decl: decl,
   659  	}
   660  	models := make(map[string]spec.Schema)
   661  	require.NoError(t, prs.Build(models))
   662  
   663  	schema := models["OtherTypes"]
   664  	assertRef(t, &schema, "named", "Named", "#/definitions/SomeStringType")
   665  	assertRef(t, &schema, "numbered", "Numbered", "#/definitions/SomeIntType")
   666  	assertProperty(t, &schema, "string", "dated", "date-time", "Dated")
   667  	assertRef(t, &schema, "timed", "Timed", "#/definitions/SomeTimedType")
   668  	assertRef(t, &schema, "petted", "Petted", "#/definitions/SomePettedType")
   669  	assertRef(t, &schema, "somethinged", "Somethinged", "#/definitions/SomethingType")
   670  	assertRef(t, &schema, "strMap", "StrMap", "#/definitions/SomeStringMap")
   671  	assertRef(t, &schema, "strArrMap", "StrArrMap", "#/definitions/SomeArrayStringMap")
   672  
   673  	assertRef(t, &schema, "manyNamed", "ManyNamed", "#/definitions/SomeStringsType")
   674  	assertRef(t, &schema, "manyNumbered", "ManyNumbered", "#/definitions/SomeIntsType")
   675  	assertArrayProperty(t, &schema, "string", "manyDated", "date-time", "ManyDated")
   676  	assertRef(t, &schema, "manyTimed", "ManyTimed", "#/definitions/SomeTimedsType")
   677  	assertRef(t, &schema, "manyPetted", "ManyPetted", "#/definitions/SomePettedsType")
   678  	assertRef(t, &schema, "manySomethinged", "ManySomethinged", "#/definitions/SomethingsType")
   679  
   680  	assertArrayRef(t, &schema, "nameds", "Nameds", "#/definitions/SomeStringType")
   681  	assertArrayRef(t, &schema, "numbereds", "Numbereds", "#/definitions/SomeIntType")
   682  	assertArrayProperty(t, &schema, "string", "dateds", "date-time", "Dateds")
   683  	assertArrayRef(t, &schema, "timeds", "Timeds", "#/definitions/SomeTimedType")
   684  	assertArrayRef(t, &schema, "petteds", "Petteds", "#/definitions/SomePettedType")
   685  	assertArrayRef(t, &schema, "somethingeds", "Somethingeds", "#/definitions/SomethingType")
   686  
   687  	assertRef(t, &schema, "modsNamed", "ModsNamed", "#/definitions/modsSomeStringType")
   688  	assertRef(t, &schema, "modsNumbered", "ModsNumbered", "#/definitions/modsSomeIntType")
   689  	assertProperty(t, &schema, "string", "modsDated", "date-time", "ModsDated")
   690  	assertRef(t, &schema, "modsTimed", "ModsTimed", "#/definitions/modsSomeTimedType")
   691  	assertRef(t, &schema, "modsPetted", "ModsPetted", "#/definitions/modsSomePettedType")
   692  
   693  	assertArrayRef(t, &schema, "modsNameds", "ModsNameds", "#/definitions/modsSomeStringType")
   694  	assertArrayRef(t, &schema, "modsNumbereds", "ModsNumbereds", "#/definitions/modsSomeIntType")
   695  	assertArrayProperty(t, &schema, "string", "modsDateds", "date-time", "ModsDateds")
   696  	assertArrayRef(t, &schema, "modsTimeds", "ModsTimeds", "#/definitions/modsSomeTimedType")
   697  	assertArrayRef(t, &schema, "modsPetteds", "ModsPetteds", "#/definitions/modsSomePettedType")
   698  
   699  	assertRef(t, &schema, "manyModsNamed", "ManyModsNamed", "#/definitions/modsSomeStringsType")
   700  	assertRef(t, &schema, "manyModsNumbered", "ManyModsNumbered", "#/definitions/modsSomeIntsType")
   701  	assertArrayProperty(t, &schema, "string", "manyModsDated", "date-time", "ManyModsDated")
   702  	assertRef(t, &schema, "manyModsTimed", "ManyModsTimed", "#/definitions/modsSomeTimedsType")
   703  	assertRef(t, &schema, "manyModsPetted", "ManyModsPetted", "#/definitions/modsSomePettedsType")
   704  	assertRef(t, &schema, "manyModsPettedPtr", "ManyModsPettedPtr", "#/definitions/modsSomePettedsPtrType")
   705  
   706  	assertProperty(t, &schema, "string", "namedAlias", "", "NamedAlias")
   707  	assertProperty(t, &schema, "integer", "numberedAlias", "int64", "NumberedAlias")
   708  	assertArrayProperty(t, &schema, "string", "namedsAlias", "", "NamedsAlias")
   709  	assertArrayProperty(t, &schema, "integer", "numberedsAlias", "int64", "NumberedsAlias")
   710  }
   711  
   712  func TestAliasedModels(t *testing.T) {
   713  	sctx := loadClassificationPkgsCtx(t)
   714  
   715  	names := []string{
   716  		"SomeStringType",
   717  		"SomeIntType",
   718  		"SomeTimeType",
   719  		"SomeTimedType",
   720  		"SomePettedType",
   721  		"SomethingType",
   722  		"SomeStringsType",
   723  		"SomeIntsType",
   724  		"SomeTimesType",
   725  		"SomeTimedsType",
   726  		"SomePettedsType",
   727  		"SomethingsType",
   728  		"SomeObject",
   729  		"SomeStringMap",
   730  		"SomeIntMap",
   731  		"SomeTimeMap",
   732  		"SomeTimedMap",
   733  		"SomePettedMap",
   734  		"SomeSomethingMap",
   735  	}
   736  
   737  	defs := make(map[string]spec.Schema)
   738  	for _, nm := range names {
   739  		decl := getClassificationModel(sctx, nm)
   740  		require.NotNil(t, decl)
   741  
   742  		prs := &schemaBuilder{
   743  			decl: decl,
   744  			ctx:  sctx,
   745  		}
   746  		require.NoError(t, prs.Build(defs))
   747  	}
   748  
   749  	for k := range defs {
   750  		for i, b := range names {
   751  			if b == k {
   752  				// remove the entry from the collection
   753  				names = append(names[:i], names[i+1:]...)
   754  			}
   755  		}
   756  	}
   757  	if assert.Empty(t, names) {
   758  		// single value types
   759  		assertDefinition(t, defs, "SomeStringType", "string", "", "")
   760  		assertDefinition(t, defs, "SomeIntType", "integer", "int64", "")
   761  		assertDefinition(t, defs, "SomeTimeType", "string", "date-time", "")
   762  		assertDefinition(t, defs, "SomeTimedType", "string", "date-time", "")
   763  		assertRefDefinition(t, defs, "SomePettedType", "#/definitions/pet", "")
   764  		assertRefDefinition(t, defs, "SomethingType", "#/definitions/Something", "")
   765  
   766  		// slice types
   767  		assertArrayDefinition(t, defs, "SomeStringsType", "string", "", "")
   768  		assertArrayDefinition(t, defs, "SomeIntsType", "integer", "int64", "")
   769  		assertArrayDefinition(t, defs, "SomeTimesType", "string", "date-time", "")
   770  		assertArrayDefinition(t, defs, "SomeTimedsType", "string", "date-time", "")
   771  		assertArrayWithRefDefinition(t, defs, "SomePettedsType", "#/definitions/pet", "")
   772  		assertArrayWithRefDefinition(t, defs, "SomethingsType", "#/definitions/Something", "")
   773  
   774  		// map types
   775  		assertMapDefinition(t, defs, "SomeObject", "object", "", "")
   776  		assertMapDefinition(t, defs, "SomeStringMap", "string", "", "")
   777  		assertMapDefinition(t, defs, "SomeIntMap", "integer", "int64", "")
   778  		assertMapDefinition(t, defs, "SomeTimeMap", "string", "date-time", "")
   779  		assertMapDefinition(t, defs, "SomeTimedMap", "string", "date-time", "")
   780  		assertMapWithRefDefinition(t, defs, "SomePettedMap", "#/definitions/pet", "")
   781  		assertMapWithRefDefinition(t, defs, "SomeSomethingMap", "#/definitions/Something", "")
   782  	}
   783  }
   784  
   785  func TestEmbeddedAllOf(t *testing.T) {
   786  	sctx := loadClassificationPkgsCtx(t)
   787  	decl := getClassificationModel(sctx, "AllOfModel")
   788  	require.NotNil(t, decl)
   789  	prs := &schemaBuilder{
   790  		ctx:  sctx,
   791  		decl: decl,
   792  	}
   793  	models := make(map[string]spec.Schema)
   794  	require.NoError(t, prs.Build(models))
   795  	schema := models["AllOfModel"]
   796  
   797  	require.Len(t, schema.AllOf, 3)
   798  	asch := schema.AllOf[0]
   799  	assertProperty(t, &asch, "integer", "age", "int32", "Age")
   800  	assertProperty(t, &asch, "integer", "id", "int64", "ID")
   801  	assertProperty(t, &asch, "string", "name", "", "Name")
   802  
   803  	asch = schema.AllOf[1]
   804  	assert.Equal(t, "#/definitions/withNotes", asch.Ref.String())
   805  
   806  	asch = schema.AllOf[2]
   807  	assertProperty(t, &asch, "string", "createdAt", "date-time", "CreatedAt")
   808  	assertProperty(t, &asch, "integer", "did", "int64", "DID")
   809  	assertProperty(t, &asch, "string", "cat", "", "Cat")
   810  }
   811  
   812  func TestStructDiscriminators(t *testing.T) {
   813  	sctx := loadClassificationPkgsCtx(t)
   814  
   815  	models := make(map[string]spec.Schema)
   816  	for _, tn := range []string{"BaseStruct", "Giraffe", "Gazelle"} {
   817  		decl := getClassificationModel(sctx, tn)
   818  		require.NotNil(t, decl)
   819  		prs := &schemaBuilder{
   820  			ctx:  sctx,
   821  			decl: decl,
   822  		}
   823  		require.NoError(t, prs.Build(models))
   824  	}
   825  
   826  	schema := models["animal"]
   827  
   828  	assert.Equal(t, "BaseStruct", schema.Extensions["x-go-name"])
   829  	assert.Equal(t, schema.Discriminator, "jsonClass")
   830  
   831  	sch := models["gazelle"]
   832  	assert.Len(t, sch.AllOf, 2)
   833  	cl, _ := sch.Extensions.GetString("x-class")
   834  	assert.Equal(t, "a.b.c.d.E", cl)
   835  	cl, _ = sch.Extensions.GetString("x-go-name")
   836  	assert.Equal(t, "Gazelle", cl)
   837  
   838  	sch = models["giraffe"]
   839  	assert.Len(t, sch.AllOf, 2)
   840  	cl, _ = sch.Extensions.GetString("x-class")
   841  	assert.Equal(t, "", cl)
   842  	cl, _ = sch.Extensions.GetString("x-go-name")
   843  	assert.Equal(t, "Giraffe", cl)
   844  
   845  	// sch = noModelDefs["lion"]
   846  
   847  	// b, _ := json.MarshalIndent(sch, "", "  ")
   848  	// fmt.Println(string(b))
   849  
   850  }
   851  
   852  func TestInterfaceDiscriminators(t *testing.T) {
   853  	sctx := loadClassificationPkgsCtx(t)
   854  	models := make(map[string]spec.Schema)
   855  	for _, tn := range []string{"BaseStruct", "Identifiable", "WaterType", "Fish", "TeslaCar", "ModelS", "ModelX", "ModelA", "Cars"} {
   856  		decl := getClassificationModel(sctx, tn)
   857  		require.NotNil(t, decl)
   858  
   859  		prs := &schemaBuilder{
   860  			ctx:  sctx,
   861  			decl: decl,
   862  		}
   863  		require.NoError(t, prs.Build(models))
   864  	}
   865  
   866  	schema, ok := models["fish"]
   867  
   868  	if assert.True(t, ok) && assert.Len(t, schema.AllOf, 5) {
   869  		sch := schema.AllOf[0]
   870  		assert.Len(t, sch.Properties, 1)
   871  		assertProperty(t, &sch, "string", "colorName", "", "ColorName")
   872  
   873  		sch = schema.AllOf[1]
   874  		assert.Equal(t, "#/definitions/extra", sch.Ref.String())
   875  
   876  		sch = schema.AllOf[2]
   877  		assert.Len(t, sch.Properties, 1)
   878  		assertProperty(t, &sch, "integer", "id", "int64", "ID")
   879  
   880  		sch = schema.AllOf[3]
   881  		assert.Equal(t, "#/definitions/water", sch.Ref.String())
   882  
   883  		sch = schema.AllOf[4]
   884  		assert.Len(t, sch.Properties, 2)
   885  		assertProperty(t, &sch, "string", "name", "", "Name")
   886  		assertProperty(t, &sch, "string", "jsonClass", "", "StructType")
   887  		assert.Equal(t, "jsonClass", sch.Discriminator)
   888  	}
   889  
   890  	schema, ok = models["modelS"]
   891  	if assert.True(t, ok) {
   892  		assert.Len(t, schema.AllOf, 2)
   893  		cl, _ := schema.Extensions.GetString("x-class")
   894  		assert.Equal(t, "com.tesla.models.ModelS", cl)
   895  		cl, _ = schema.Extensions.GetString("x-go-name")
   896  		assert.Equal(t, "ModelS", cl)
   897  
   898  		sch := schema.AllOf[0]
   899  		assert.Equal(t, "#/definitions/TeslaCar", sch.Ref.String())
   900  		sch = schema.AllOf[1]
   901  		assert.Len(t, sch.Properties, 1)
   902  		assertProperty(t, &sch, "string", "edition", "", "Edition")
   903  	}
   904  
   905  	schema, ok = models["modelA"]
   906  	if assert.True(t, ok) {
   907  
   908  		cl, _ := schema.Extensions.GetString("x-go-name")
   909  		assert.Equal(t, "ModelA", cl)
   910  
   911  		sch, ok := schema.Properties["Tesla"]
   912  		if assert.True(t, ok) {
   913  			assert.Equal(t, "#/definitions/TeslaCar", sch.Ref.String())
   914  		}
   915  
   916  		assertProperty(t, &schema, "integer", "doors", "int64", "Doors")
   917  	}
   918  }
   919  
   920  func TestAddExtension(t *testing.T) {
   921  	ve := &spec.VendorExtensible{
   922  		Extensions: make(spec.Extensions),
   923  	}
   924  
   925  	key := "x-go-name"
   926  	value := "Name"
   927  	addExtension(ve, key, value)
   928  	assert.Equal(t, value, ve.Extensions[key].(string))
   929  
   930  	key2 := "x-go-package"
   931  	value2 := "schema"
   932  	_ = os.Setenv("SWAGGER_GENERATE_EXTENSION", "true")
   933  	addExtension(ve, key2, value2)
   934  	assert.Equal(t, value2, ve.Extensions[key2].(string))
   935  
   936  	key3 := "x-go-class"
   937  	value3 := "Spec"
   938  	_ = os.Setenv("SWAGGER_GENERATE_EXTENSION", "false")
   939  	addExtension(ve, key3, value3)
   940  	assert.Equal(t, nil, ve.Extensions[key3])
   941  }
   942  
   943  func getClassificationModel(sctx *scanCtx, nm string) *entityDecl {
   944  	decl, ok := sctx.FindDecl("github.com/AngusLu/go-swagger/fixtures/goparsing/classification/models", nm)
   945  	if !ok {
   946  		return nil
   947  	}
   948  	return decl
   949  }
   950  
   951  func assertArrayProperty(t testing.TB, schema *spec.Schema, typeName, jsonName, format, goName string) {
   952  	prop := schema.Properties[jsonName]
   953  	assert.NotEmpty(t, prop.Type)
   954  	assert.True(t, prop.Type.Contains("array"))
   955  	assert.NotNil(t, prop.Items)
   956  	if typeName != "" {
   957  		assert.Equal(t, typeName, prop.Items.Schema.Type[0])
   958  	}
   959  	assert.Equal(t, goName, prop.Extensions["x-go-name"])
   960  	assert.Equal(t, format, prop.Items.Schema.Format)
   961  }
   962  
   963  func assertArrayRef(t testing.TB, schema *spec.Schema, jsonName, goName, fragment string) {
   964  	assertArrayProperty(t, schema, "", jsonName, "", goName)
   965  	psch := schema.Properties[jsonName].Items.Schema
   966  	assert.Equal(t, fragment, psch.Ref.String())
   967  }
   968  
   969  func assertProperty(t testing.TB, schema *spec.Schema, typeName, jsonName, format, goName string) {
   970  	if typeName == "" {
   971  		assert.Empty(t, schema.Properties[jsonName].Type)
   972  	} else if assert.NotEmpty(t, schema.Properties[jsonName].Type) {
   973  		assert.Equal(t, typeName, schema.Properties[jsonName].Type[0])
   974  	}
   975  	if goName == "" {
   976  		assert.Equal(t, nil, schema.Properties[jsonName].Extensions["x-go-name"])
   977  	} else {
   978  		assert.Equal(t, goName, schema.Properties[jsonName].Extensions["x-go-name"])
   979  	}
   980  	assert.Equal(t, format, schema.Properties[jsonName].Format)
   981  }
   982  
   983  func assertRef(t testing.TB, schema *spec.Schema, jsonName, _, fragment string) {
   984  	assert.Empty(t, schema.Properties[jsonName].Type)
   985  	psch := schema.Properties[jsonName]
   986  	assert.Equal(t, fragment, psch.Ref.String())
   987  }
   988  
   989  func assertDefinition(t testing.TB, defs map[string]spec.Schema, defName, typeName, formatName, goName string) {
   990  	schema, ok := defs[defName]
   991  	if assert.True(t, ok) {
   992  
   993  		if assert.NotEmpty(t, schema.Type) {
   994  			assert.Equal(t, typeName, schema.Type[0])
   995  			if goName != "" {
   996  				assert.Equal(t, goName, schema.Extensions["x-go-name"])
   997  			} else {
   998  				assert.Nil(t, schema.Extensions["x-go-name"])
   999  			}
  1000  			assert.Equal(t, formatName, schema.Format)
  1001  		}
  1002  	}
  1003  }
  1004  
  1005  func assertMapDefinition(t testing.TB, defs map[string]spec.Schema, defName, typeName, formatName, goName string) {
  1006  	schema, ok := defs[defName]
  1007  	if assert.True(t, ok) {
  1008  		if assert.NotEmpty(t, schema.Type) {
  1009  			assert.Equal(t, "object", schema.Type[0])
  1010  			adl := schema.AdditionalProperties
  1011  			if assert.NotNil(t, adl) && assert.NotNil(t, adl.Schema) {
  1012  				assert.Equal(t, typeName, adl.Schema.Type[0])
  1013  				assert.Equal(t, formatName, adl.Schema.Format)
  1014  			}
  1015  			if goName != "" {
  1016  				assert.Equal(t, goName, schema.Extensions["x-go-name"])
  1017  			} else {
  1018  				assert.Nil(t, schema.Extensions["x-go-name"])
  1019  			}
  1020  		}
  1021  	}
  1022  }
  1023  
  1024  func assertMapWithRefDefinition(t testing.TB, defs map[string]spec.Schema, defName, refURL, goName string) {
  1025  	schema, ok := defs[defName]
  1026  	if assert.True(t, ok) {
  1027  		if assert.NotEmpty(t, schema.Type) {
  1028  			assert.Equal(t, "object", schema.Type[0])
  1029  			adl := schema.AdditionalProperties
  1030  			if assert.NotNil(t, adl) && assert.NotNil(t, adl.Schema) {
  1031  				if assert.NotZero(t, adl.Schema.Ref) {
  1032  					assert.Equal(t, refURL, adl.Schema.Ref.String())
  1033  				}
  1034  			}
  1035  			if goName != "" {
  1036  				assert.Equal(t, goName, schema.Extensions["x-go-name"])
  1037  			} else {
  1038  				assert.Nil(t, schema.Extensions["x-go-name"])
  1039  			}
  1040  		}
  1041  	}
  1042  }
  1043  
  1044  func assertArrayDefinition(t testing.TB, defs map[string]spec.Schema, defName, typeName, formatName, goName string) {
  1045  	schema, ok := defs[defName]
  1046  	if assert.True(t, ok) {
  1047  		if assert.NotEmpty(t, schema.Type) {
  1048  			assert.Equal(t, "array", schema.Type[0])
  1049  			adl := schema.Items
  1050  			if assert.NotNil(t, adl) && assert.NotNil(t, adl.Schema) {
  1051  				assert.Equal(t, typeName, adl.Schema.Type[0])
  1052  				assert.Equal(t, formatName, adl.Schema.Format)
  1053  			}
  1054  			if goName != "" {
  1055  				assert.Equal(t, goName, schema.Extensions["x-go-name"])
  1056  			} else {
  1057  				assert.Nil(t, schema.Extensions["x-go-name"])
  1058  			}
  1059  		}
  1060  	}
  1061  }
  1062  
  1063  func assertArrayWithRefDefinition(t testing.TB, defs map[string]spec.Schema, defName, refURL, goName string) {
  1064  	schema, ok := defs[defName]
  1065  	if assert.True(t, ok) {
  1066  		if assert.NotEmpty(t, schema.Type) {
  1067  			assert.Equal(t, "array", schema.Type[0])
  1068  			adl := schema.Items
  1069  			if assert.NotNil(t, adl) && assert.NotNil(t, adl.Schema) {
  1070  				if assert.NotZero(t, adl.Schema.Ref) {
  1071  					assert.Equal(t, refURL, adl.Schema.Ref.String())
  1072  				}
  1073  			}
  1074  			if goName != "" {
  1075  				assert.Equal(t, goName, schema.Extensions["x-go-name"])
  1076  			} else {
  1077  				assert.Nil(t, schema.Extensions["x-go-name"])
  1078  			}
  1079  		}
  1080  	}
  1081  }
  1082  
  1083  func assertRefDefinition(t testing.TB, defs map[string]spec.Schema, defName, refURL, goName string) {
  1084  	schema, ok := defs[defName]
  1085  	if assert.True(t, ok) {
  1086  		if assert.NotZero(t, schema.Ref) {
  1087  			url := schema.Ref.String()
  1088  			assert.Equal(t, refURL, url)
  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 assertMapProperty(t testing.TB, schema *spec.Schema, typeName, jsonName, format, goName string) {
  1099  	prop := schema.Properties[jsonName]
  1100  	assert.NotEmpty(t, prop.Type)
  1101  	assert.True(t, prop.Type.Contains("object"))
  1102  	assert.NotNil(t, prop.AdditionalProperties)
  1103  	if typeName != "" {
  1104  		assert.Equal(t, typeName, prop.AdditionalProperties.Schema.Type[0])
  1105  	}
  1106  	assert.Equal(t, goName, prop.Extensions["x-go-name"])
  1107  	assert.Equal(t, format, prop.AdditionalProperties.Schema.Format)
  1108  }
  1109  
  1110  func assertMapRef(t testing.TB, schema *spec.Schema, jsonName, goName, fragment string) {
  1111  	assertMapProperty(t, schema, "", jsonName, "", goName)
  1112  	psch := schema.Properties[jsonName].AdditionalProperties.Schema
  1113  	assert.Equal(t, fragment, psch.Ref.String())
  1114  }