github.com/djarvur/go-swagger@v0.18.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 }