github.com/go-swagger/go-swagger@v0.31.0/generator/discriminators_test.go (about)

     1  package generator
     2  
     3  import (
     4  	"bytes"
     5  	"testing"
     6  
     7  	"github.com/go-openapi/analysis"
     8  	"github.com/go-openapi/loads"
     9  	"github.com/go-openapi/swag"
    10  	"github.com/stretchr/testify/assert"
    11  	"github.com/stretchr/testify/require"
    12  )
    13  
    14  func TestBuildDiscriminatorMap(t *testing.T) {
    15  	specDoc, err := loads.Spec("../fixtures/codegen/todolist.discriminators.yml")
    16  	require.NoError(t, err)
    17  
    18  	di := discriminatorInfo(analysis.New(specDoc.Spec()))
    19  	assert.Len(t, di.Discriminators, 1)
    20  	assert.Len(t, di.Discriminators["#/definitions/Pet"].Children, 2)
    21  	assert.Len(t, di.Discriminated, 2)
    22  }
    23  
    24  func TestGenerateModel_DiscriminatorSlices(t *testing.T) {
    25  	specDoc, err := loads.Spec("../fixtures/codegen/todolist.discriminators.yml")
    26  	require.NoError(t, err)
    27  
    28  	definitions := specDoc.Spec().Definitions
    29  	k := "Kennel"
    30  	schema := definitions[k]
    31  	opts := opts()
    32  	genModel, err := makeGenDefinition(k, "models", schema, specDoc, opts)
    33  	require.NoError(t, err)
    34  	assert.True(t, genModel.HasBaseType)
    35  
    36  	buf := bytes.NewBuffer(nil)
    37  	err = opts.templates.MustGet("model").Execute(buf, genModel)
    38  	require.NoError(t, err)
    39  
    40  	b, err := opts.LanguageOpts.FormatContent("has_discriminator.go", buf.Bytes())
    41  	require.NoErrorf(t, err, buf.String())
    42  
    43  	res := string(b)
    44  	assertInCode(t, "type Kennel struct {", res)
    45  	assertInCode(t, "ID int64 `json:\"id,omitempty\"`", res)
    46  	assertInCode(t, "Pets []Pet `json:\"pets\"`", res)
    47  	assertInCode(t, "if err := m.petsField[i].Validate(formats); err != nil {", res)
    48  	assertInCode(t, "m.validatePet", res)
    49  }
    50  
    51  func TestGenerateModel_Discriminators(t *testing.T) {
    52  	defer discardOutput()()
    53  
    54  	specDoc, e := loads.Spec("../fixtures/codegen/todolist.discriminators.yml")
    55  	require.NoError(t, e)
    56  
    57  	definitions := specDoc.Spec().Definitions
    58  
    59  	for _, k := range []string{"cat", "Dog"} {
    60  		schema := definitions[k]
    61  		opts := opts()
    62  		genModel, err := makeGenDefinition(k, "models", schema, specDoc, opts)
    63  		require.NoError(t, err)
    64  
    65  		assert.True(t, genModel.IsComplexObject)
    66  		assert.Equal(t, "petType", genModel.DiscriminatorField)
    67  		assert.Equal(t, k, genModel.DiscriminatorValue)
    68  
    69  		buf := bytes.NewBuffer(nil)
    70  		err = opts.templates.MustGet("model").Execute(buf, genModel)
    71  		require.NoError(t, err)
    72  
    73  		b, err := opts.LanguageOpts.FormatContent("discriminated.go", buf.Bytes())
    74  		require.NoErrorf(t, err, buf.String())
    75  
    76  		res := string(b)
    77  		assertNotInCode(t, "m.Pet.Validate", res)
    78  		assertInCode(t, "if err := m.validateName(formats); err != nil {", res)
    79  
    80  		if k == "Dog" {
    81  			assertInCode(t, "func (m *Dog) validatePackSize(formats strfmt.Registry) error {", res)
    82  			assertInCode(t, "if err := m.validatePackSize(formats); err != nil {", res)
    83  			assertInCode(t, "PackSize: m.PackSize,", res)
    84  			assertInCode(t, "validate.Required(\"packSize\", \"body\", m.PackSize)", res)
    85  		} else {
    86  			assertInCode(t, "func (m *Cat) validateHuntingSkill(formats strfmt.Registry) error {", res)
    87  			assertInCode(t, "if err := m.validateHuntingSkill(formats); err != nil {", res)
    88  			assertInCode(t, "if err := m.validateHuntingSkillEnum(\"huntingSkill\", \"body\", *m.HuntingSkill); err != nil {", res)
    89  			assertInCode(t, "HuntingSkill: m.HuntingSkill", res)
    90  		}
    91  
    92  		assertInCode(t, "Name *string `json:\"name\"`", res)
    93  		assertInCode(t, "PetType string `json:\"petType\"`", res)
    94  
    95  		assertInCode(t, "result.nameField = base.Name", res)
    96  		assertInCode(t, "if base.PetType != result.PetType() {", res)
    97  		assertInCode(t, "return errors.New(422, \"invalid petType value: %q\", base.PetType)", res)
    98  
    99  		kk := swag.ToGoName(k)
   100  		assertInCode(t, "func (m *"+kk+") Name() *string", res)
   101  		assertInCode(t, "func (m *"+kk+") SetName(val *string)", res)
   102  		assertInCode(t, "func (m *"+kk+") PetType() string", res)
   103  		assertInCode(t, "func (m *"+kk+") SetPetType(val string)", res)
   104  		assertInCode(t, "validate.Required(\"name\", \"body\", m.Name())", res)
   105  	}
   106  
   107  	k := "Pet"
   108  	schema := definitions[k]
   109  	opts := opts()
   110  	genModel, err := makeGenDefinition(k, "models", schema, specDoc, opts)
   111  	require.NoError(t, err)
   112  
   113  	assert.True(t, genModel.IsComplexObject)
   114  	assert.Equal(t, "petType", genModel.DiscriminatorField)
   115  	assert.Len(t, genModel.Discriminates, 3)
   116  	assert.Empty(t, genModel.ExtraSchemas)
   117  	assert.Equal(t, "Pet", genModel.Discriminates["Pet"])
   118  	assert.Equal(t, "Cat", genModel.Discriminates["cat"])
   119  	assert.Equal(t, "Dog", genModel.Discriminates["Dog"])
   120  
   121  	buf := bytes.NewBuffer(nil)
   122  	err = opts.templates.MustGet("model").Execute(buf, genModel)
   123  	require.NoError(t, err)
   124  
   125  	b, err := opts.LanguageOpts.FormatContent("with_discriminator.go", buf.Bytes())
   126  	require.NoErrorf(t, err, buf.String())
   127  
   128  	res := string(b)
   129  	assertInCode(t, "type Pet interface {", res)
   130  	assertInCode(t, "runtime.Validatable", res)
   131  	assertInCode(t, "Name() *string", res)
   132  	assertInCode(t, "SetName(*string)", res)
   133  	assertInCode(t, "PetType() string", res)
   134  	assertInCode(t, "SetPetType(string)", res)
   135  	assertInCode(t, "type pet struct {", res)
   136  	assertInCode(t, "UnmarshalPet(reader io.Reader, consumer runtime.Consumer) (Pet, error)", res)
   137  	assertInCode(t, "PetType string `json:\"petType\"`", res)
   138  	assertInCode(t, "validate.RequiredString(\"petType\"", res)
   139  	assertInCode(t, "switch getType.PetType {", res)
   140  	assertInCode(t, "var result pet", res)
   141  	assertInCode(t, "var result Cat", res)
   142  	assertInCode(t, "var result Dog", res)
   143  }
   144  
   145  func TestGenerateModel_UsesDiscriminator(t *testing.T) {
   146  	defer discardOutput()()
   147  
   148  	specDoc, err := loads.Spec("../fixtures/codegen/todolist.discriminators.yml")
   149  	require.NoError(t, err)
   150  
   151  	definitions := specDoc.Spec().Definitions
   152  	k := "WithPet"
   153  	schema := definitions[k]
   154  	opts := opts()
   155  	genModel, err := makeGenDefinition(k, "models", schema, specDoc, opts)
   156  	require.NoError(t, err)
   157  
   158  	require.True(t, genModel.HasBaseType)
   159  
   160  	buf := bytes.NewBuffer(nil)
   161  	err = opts.templates.MustGet("model").Execute(buf, genModel)
   162  	require.NoError(t, err)
   163  
   164  	b, err := opts.LanguageOpts.FormatContent("has_discriminator.go", buf.Bytes())
   165  	require.NoErrorf(t, err, buf.String())
   166  	res := string(b)
   167  	assertInCode(t, "type WithPet struct {", res)
   168  	assertInCode(t, "ID int64 `json:\"id,omitempty\"`", res)
   169  	assertInCode(t, "petField Pet", res)
   170  	assertInCode(t, "if err := m.Pet().Validate(formats); err != nil {", res)
   171  	assertInCode(t, "m.validatePet", res)
   172  }
   173  
   174  func TestGenerateClient_OKResponseWithDiscriminator(t *testing.T) {
   175  	defer discardOutput()()
   176  
   177  	specDoc, err := loads.Spec("../fixtures/codegen/todolist.discriminators.yml")
   178  	require.NoError(t, err)
   179  
   180  	method, path, op, ok := analysis.New(specDoc.Spec()).OperationForName("modelOp")
   181  	require.True(t, ok)
   182  
   183  	opts := opts()
   184  	bldr := codeGenOpBuilder{
   185  		Name:          "modelOp",
   186  		Method:        method,
   187  		Path:          path,
   188  		APIPackage:    "restapi",
   189  		ModelsPackage: "models",
   190  		Principal:     "",
   191  		Target:        ".",
   192  		Doc:           specDoc,
   193  		PristineDefs:  specDoc.Pristine(),
   194  		Analyzed:      analysis.New(specDoc.Spec()),
   195  		Operation:     *op,
   196  		Authed:        false,
   197  		DefaultScheme: "http",
   198  		ExtraSchemas:  make(map[string]GenSchema),
   199  		GenOpts:       opts,
   200  	}
   201  
   202  	genOp, err := bldr.MakeOperation()
   203  	require.NoError(t, err)
   204  
   205  	assert.True(t, genOp.Responses[0].Schema.IsBaseType)
   206  	var buf bytes.Buffer
   207  	err = opts.templates.MustGet("clientResponse").Execute(&buf, genOp)
   208  	require.NoError(t, err)
   209  
   210  	res := buf.String()
   211  	assertInCode(t, "Payload models.Pet", res)
   212  	assertInCode(t, "o.Payload = payload", res)
   213  	assertInCode(t, "payload, err := models.UnmarshalPet(response.Body(), consumer)", res)
   214  }
   215  
   216  func TestGenerateServer_Parameters(t *testing.T) {
   217  	defer discardOutput()()
   218  
   219  	specDoc, err := loads.Spec("../fixtures/codegen/todolist.discriminators.yml")
   220  	require.NoError(t, err)
   221  
   222  	method, path, op, ok := analysis.New(specDoc.Spec()).OperationForName("modelOp")
   223  	require.True(t, ok)
   224  
   225  	opts := opts()
   226  	bldr := codeGenOpBuilder{
   227  		Name:          "modelOp",
   228  		Method:        method,
   229  		Path:          path,
   230  		APIPackage:    "restapi",
   231  		ModelsPackage: "models",
   232  		Principal:     "",
   233  		Target:        ".",
   234  		Doc:           specDoc,
   235  		Analyzed:      analysis.New(specDoc.Spec()),
   236  		Operation:     *op,
   237  		Authed:        false,
   238  		DefaultScheme: "http",
   239  		ExtraSchemas:  make(map[string]GenSchema),
   240  		GenOpts:       opts,
   241  	}
   242  	genOp, err := bldr.MakeOperation()
   243  	require.NoError(t, err)
   244  
   245  	assert.True(t, genOp.Responses[0].Schema.IsBaseType)
   246  	var buf bytes.Buffer
   247  	err = opts.templates.MustGet("serverParameter").Execute(&buf, genOp)
   248  	require.NoErrorf(t, err, buf.String())
   249  
   250  	res := buf.String()
   251  	assertInCode(t, "Pet models.Pet", res)
   252  	assertInCode(t, "body, err := models.UnmarshalPet(r.Body, route.Consumer)", res)
   253  	assertInCode(t, "o.Pet = body", res)
   254  }
   255  
   256  func TestGenerateModel_Discriminator_Billforward(t *testing.T) {
   257  	defer discardOutput()()
   258  
   259  	specDoc, err := loads.Spec("../fixtures/codegen/billforward.discriminators.yml")
   260  	require.NoError(t, err)
   261  
   262  	definitions := specDoc.Spec().Definitions
   263  	k := "FlatPricingComponent"
   264  	schema := definitions[k]
   265  	opts := opts()
   266  	genModel, err := makeGenDefinition(k, "models", schema, specDoc, opts)
   267  	require.NoError(t, err)
   268  	require.True(t, genModel.IsSubType)
   269  
   270  	buf := bytes.NewBuffer(nil)
   271  	err = opts.templates.MustGet("model").Execute(buf, genModel)
   272  	require.NoError(t, err)
   273  
   274  	b, err := opts.LanguageOpts.FormatContent("has_discriminator.go", buf.Bytes())
   275  	require.NoErrorf(t, err, buf.String())
   276  
   277  	res := string(b)
   278  	assertNotInCode(t, "for i := 0; i < len(m.PriceExplanation()); i++", res)
   279  }
   280  
   281  func TestGenerateModel_Bitbucket_Repository(t *testing.T) {
   282  	defer discardOutput()()
   283  
   284  	specDoc, err := loads.Spec("../fixtures/codegen/bitbucket.json")
   285  	require.NoError(t, err)
   286  
   287  	definitions := specDoc.Spec().Definitions
   288  	k := "repository"
   289  	schema := definitions[k]
   290  	opts := opts()
   291  	genModel, err := makeGenDefinition(k, "models", schema, specDoc, opts)
   292  	require.NoError(t, err)
   293  
   294  	assert.True(t, genModel.IsNullable)
   295  	for _, gm := range genModel.AllOf {
   296  		for _, p := range gm.Properties {
   297  			if p.Name == "parent" {
   298  				assert.True(t, p.IsNullable)
   299  			}
   300  		}
   301  	}
   302  
   303  	buf := bytes.NewBuffer(nil)
   304  	err = opts.templates.MustGet("model").Execute(buf, genModel)
   305  	require.NoError(t, err)
   306  
   307  	b, err := opts.LanguageOpts.FormatContent("repository.go", buf.Bytes())
   308  	require.NoErrorf(t, err, buf.String())
   309  
   310  	res := string(b)
   311  	assertInCode(t, "Parent *Repository", res)
   312  	assertNotInCode(t, "Parent Repository", res)
   313  }
   314  
   315  func TestGenerateModel_Bitbucket_WebhookSubscription(t *testing.T) {
   316  	defer discardOutput()()
   317  
   318  	specDoc, err := loads.Spec("../fixtures/codegen/bitbucket.json")
   319  	require.NoError(t, err)
   320  
   321  	definitions := specDoc.Spec().Definitions
   322  	k := "webhook_subscription"
   323  	schema := definitions[k]
   324  	opts := opts()
   325  	genModel, err := makeGenDefinition(k, "models", schema, specDoc, opts)
   326  	require.NoError(t, err)
   327  
   328  	buf := bytes.NewBuffer(nil)
   329  	err = opts.templates.MustGet("model").Execute(buf, genModel)
   330  	require.NoError(t, err)
   331  
   332  	b, err := opts.LanguageOpts.FormatContent("webhook_subscription.go", buf.Bytes())
   333  	require.NoErrorf(t, err, buf.String())
   334  
   335  	res := string(b)
   336  	assertInCode(t, "result.subjectField", res)
   337  	assertInCode(t, "Subject: m.Subject()", res)
   338  }
   339  
   340  func TestGenerateModel_Issue319(t *testing.T) {
   341  	defer discardOutput()()
   342  
   343  	specDoc, err := loads.Spec("../fixtures/bugs/319/swagger.yml")
   344  	require.NoError(t, err)
   345  
   346  	definitions := specDoc.Spec().Definitions
   347  	k := "Container"
   348  	schema := definitions[k]
   349  	opts := opts()
   350  	genModel, err := makeGenDefinition(k, "models", schema, specDoc, opts)
   351  	require.NoError(t, err)
   352  	require.Equal(t, "map[string]Base", genModel.Properties[0].GoType)
   353  
   354  	buf := bytes.NewBuffer(nil)
   355  	err = opts.templates.MustGet("model").Execute(buf, genModel)
   356  	require.NoError(t, err)
   357  
   358  	b, err := opts.LanguageOpts.FormatContent("ifacedmap.go", buf.Bytes())
   359  	require.NoErrorf(t, err, buf.String())
   360  
   361  	res := string(b)
   362  	assertInCode(t, "MapNoWorky map[string]Base", res)
   363  }
   364  
   365  func TestGenerateModel_Issue541(t *testing.T) {
   366  	defer discardOutput()()
   367  
   368  	specDoc, err := loads.Spec("../fixtures/bugs/541/swagger.json")
   369  	require.NoError(t, err)
   370  
   371  	definitions := specDoc.Spec().Definitions
   372  	k := "Lion"
   373  	schema := definitions[k]
   374  	opts := opts()
   375  	genModel, err := makeGenDefinition(k, "models", schema, specDoc, opts)
   376  	require.NoError(t, err)
   377  	require.NotEmpty(t, genModel.AllOf)
   378  
   379  	buf := bytes.NewBuffer(nil)
   380  	err = opts.templates.MustGet("model").Execute(buf, genModel)
   381  	require.NoError(t, err)
   382  
   383  	b, err := opts.LanguageOpts.FormatContent("lion.go", buf.Bytes())
   384  	require.NoErrorf(t, err, buf.String())
   385  
   386  	res := string(b)
   387  	assertInCode(t, "Cat", res)
   388  	assertInCode(t, "m.Cat.Validate(formats)", res)
   389  }
   390  
   391  func TestGenerateModel_Issue436(t *testing.T) {
   392  	defer discardOutput()()
   393  
   394  	specDoc, err := loads.Spec("../fixtures/bugs/436/swagger.yml")
   395  	require.NoError(t, err)
   396  
   397  	definitions := specDoc.Spec().Definitions
   398  	k := "Image"
   399  	schema := definitions[k]
   400  	opts := opts()
   401  	genModel, err := makeGenDefinition(k, "models", schema, specDoc, opts)
   402  	require.NoError(t, err)
   403  	require.NotEmpty(t, genModel.AllOf)
   404  
   405  	buf := bytes.NewBuffer(nil)
   406  	err = opts.templates.MustGet("model").Execute(buf, genModel)
   407  	require.NoError(t, err)
   408  
   409  	b, err := opts.LanguageOpts.FormatContent("lion.go", buf.Bytes())
   410  	require.NoErrorf(t, err, buf.String())
   411  
   412  	res := string(b)
   413  	assertInCode(t, "Links", res)
   414  	assertInCode(t, "m.Links.Validate(formats)", res)
   415  	assertInCode(t, "Created *strfmt.DateTime `json:\"created\"`", res)
   416  	assertInCode(t, "ImageID *string `json:\"imageId\"`", res)
   417  	assertInCode(t, "Size *int64 `json:\"size\"`", res)
   418  }
   419  
   420  func TestGenerateModel_Issue740(t *testing.T) {
   421  	defer discardOutput()()
   422  
   423  	specDoc, err := loads.Spec("../fixtures/bugs/740/swagger.yml")
   424  	require.NoError(t, err)
   425  
   426  	definitions := specDoc.Spec().Definitions
   427  	k := "Bar"
   428  	schema := definitions[k]
   429  	opts := opts()
   430  	genModel, err := makeGenDefinition(k, "models", schema, specDoc, opts)
   431  	require.NoError(t, err)
   432  	require.NotEmpty(t, genModel.AllOf)
   433  
   434  	buf := bytes.NewBuffer(nil)
   435  	err = opts.templates.MustGet("model").Execute(buf, genModel)
   436  	require.NoError(t, err)
   437  
   438  	b, err := opts.LanguageOpts.FormatContent("bar.go", buf.Bytes())
   439  	require.NoErrorf(t, err, buf.String())
   440  
   441  	res := string(b)
   442  	assertInCode(t, "Foo", res)
   443  	assertInCode(t, "m.Foo.Validate(formats)", res)
   444  }
   445  
   446  func TestGenerateModel_Issue743(t *testing.T) {
   447  	defer discardOutput()()
   448  
   449  	specDoc, err := loads.Spec("../fixtures/bugs/743/swagger.yml")
   450  	require.NoError(t, err)
   451  
   452  	definitions := specDoc.Spec().Definitions
   453  	k := "Awol"
   454  	schema := definitions[k]
   455  	opts := opts()
   456  	genModel, err := makeGenDefinition(k, "models", schema, specDoc, opts)
   457  	require.NoError(t, err)
   458  	require.NotEmpty(t, genModel.AllOf)
   459  
   460  	buf := bytes.NewBuffer(nil)
   461  	err = opts.templates.MustGet("model").Execute(buf, genModel)
   462  	require.NoError(t, err)
   463  
   464  	b, err := opts.LanguageOpts.FormatContent("awol.go", buf.Bytes())
   465  	require.NoErrorf(t, err, buf.String())
   466  
   467  	res := string(b)
   468  	assertInCode(t, "Foo", res)
   469  	assertInCode(t, "Bar", res)
   470  	assertInCode(t, "m.Foo.Validate(formats)", res)
   471  	assertInCode(t, "m.Bar.Validate(formats)", res)
   472  	assertInCode(t, "swag.WriteJSON(m.Foo)", res)
   473  	assertInCode(t, "swag.WriteJSON(m.Bar)", res)
   474  	assertInCode(t, "swag.ReadJSON(raw, &aO0)", res)
   475  	assertInCode(t, "swag.ReadJSON(raw, &aO1)", res)
   476  	assertInCode(t, "m.Foo = aO0", res)
   477  	assertInCode(t, "m.Bar = aO1", res)
   478  }