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 }