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

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