github.com/go-swagger/go-swagger@v0.31.0/generator/shared_test.go (about) 1 package generator 2 3 import ( 4 "fmt" 5 "log" 6 "os" 7 "path" 8 "path/filepath" 9 "runtime" 10 "testing" 11 12 "github.com/go-openapi/analysis" 13 "github.com/go-openapi/loads" 14 "github.com/stretchr/testify/assert" 15 "github.com/stretchr/testify/require" 16 ) 17 18 const ( 19 defaultAPIPackage = "operations" 20 defaultClientPackage = "client" 21 defaultModelPackage = "models" 22 defaultServerPackage = "restapi" 23 ) 24 25 // Perform common initialization of template repository before running tests. 26 // This allows to run tests unitarily (e.g. go test -run xxx ). 27 func TestMain(m *testing.M) { 28 // initializations to run tests in this package 29 log.SetFlags(log.LstdFlags | log.Lshortfile) 30 templates.LoadDefaults() 31 initSchemaValidationTest() 32 os.Exit(m.Run()) 33 } 34 35 func opts() *GenOpts { 36 var opts GenOpts 37 opts.IncludeValidator = true 38 opts.IncludeModel = true 39 if err := opts.EnsureDefaults(); err != nil { 40 panic(err) 41 } 42 return &opts 43 } 44 45 func testGenOpts() *GenOpts { 46 g := &GenOpts{} 47 g.Target = "." 48 g.APIPackage = defaultAPIPackage 49 g.ModelPackage = defaultModelPackage 50 g.ServerPackage = defaultServerPackage 51 g.ClientPackage = defaultClientPackage 52 g.Principal = "" 53 g.DefaultScheme = "http" 54 g.IncludeModel = true 55 g.IncludeValidator = true 56 g.IncludeModel = true 57 g.IncludeHandler = true 58 g.IncludeParameters = true 59 g.IncludeResponses = true 60 g.IncludeMain = false 61 g.IncludeSupport = true 62 g.ExcludeSpec = true 63 g.TemplateDir = "" 64 g.DumpData = false 65 66 if err := g.EnsureDefaults(); err != nil { 67 panic(err) 68 } 69 return g 70 } 71 72 // TODO: there is a catch, since these methods are sensitive 73 // to the CWD of the current swagger command (or go 74 // generate when working on resulting template) 75 // NOTE: 76 // Errors in CheckOpts are hard to simulate since 77 // they occur only on os.Getwd() errors 78 // Windows style path is difficult to test on unix 79 // since the filepath pkg is platform dependent 80 func TestShared_CheckOpts(t *testing.T) { 81 defer discardOutput()() 82 testPath := filepath.Join("a", "b", "b") 83 84 opts := new(GenOpts) 85 _ = opts.EnsureDefaults() 86 cwd, _ := os.Getwd() 87 opts.Spec = "../fixtures/codegen/simplesearch.yml" 88 89 opts.Target = filepath.Join(".", "a", "b", "c") 90 opts.ServerPackage = filepath.Join(cwd, "a", "b", "c") 91 err := opts.CheckOpts() 92 require.Error(t, err) 93 94 opts.Target = filepath.Join(cwd, "a", "b", "c") 95 opts.ServerPackage = testPath 96 opts.Spec = filepath.Join(cwd, "nowhere", "swagger.yaml") 97 err = opts.CheckOpts() 98 require.Error(t, err) 99 100 opts.Target = filepath.Join(cwd, "a", "b", "c") 101 opts.ServerPackage = testPath 102 opts.Spec = "https://ab/c" 103 err = opts.CheckOpts() 104 require.NoError(t, err) 105 106 opts.Target = filepath.Join(cwd, "a", "b", "c") 107 opts.ServerPackage = testPath 108 opts.Spec = "http://ab/c" 109 err = opts.CheckOpts() 110 require.NoError(t, err) 111 112 opts.Target = filepath.Join("a", "b", "c") 113 opts.ServerPackage = testPath 114 opts.Spec = filepath.Join(cwd, "..", "fixtures", "codegen", "swagger-codegen-tests.json") 115 err = opts.CheckOpts() 116 require.NoError(t, err) 117 118 opts.Target = filepath.Join("a", "b", "c") 119 opts.ServerPackage = testPath 120 opts.Spec = filepath.Join("..", "fixtures", "codegen", "swagger-codegen-tests.json") 121 err = opts.CheckOpts() 122 require.NoError(t, err) 123 124 opts = nil 125 err = opts.CheckOpts() 126 require.Error(t, err) 127 } 128 129 func TestShared_EnsureDefaults(t *testing.T) { 130 opts := &GenOpts{} 131 require.NoError(t, opts.EnsureDefaults()) 132 assert.True(t, opts.defaultsEnsured) 133 opts.DefaultConsumes = "https" 134 _ = opts.EnsureDefaults() 135 assert.Equal(t, "https", opts.DefaultConsumes) 136 } 137 138 // TargetPath and SpecPath are used in server.gotmpl 139 // as template variables: {{ .TestTargetPath }} and 140 // {{ .SpecPath }}, to construct the go generate 141 // directive. 142 func TestShared_TargetPath(t *testing.T) { 143 defer discardOutput()() 144 145 cwd, _ := os.Getwd() 146 147 // relative target 148 opts := new(GenOpts) 149 _ = opts.EnsureDefaults() 150 opts.Target = filepath.Join(".", "a", "b", "c") 151 opts.ServerPackage = "y" 152 expected := filepath.Join("..", "..", "c") 153 result := opts.TargetPath() 154 assert.Equal(t, expected, result) 155 156 // relative target, server path 157 opts = new(GenOpts) 158 _ = opts.EnsureDefaults() 159 opts.Target = filepath.Join(".", "a", "b", "c") 160 opts.ServerPackage = "y/z" 161 expected = filepath.Join("..", "..", "..", "c") 162 result = opts.TargetPath() 163 assert.Equal(t, expected, result) 164 165 // absolute target 166 opts = new(GenOpts) 167 _ = opts.EnsureDefaults() 168 opts.Target = filepath.Join(cwd, "a", "b", "c") 169 opts.ServerPackage = "y" 170 expected = filepath.Join("..", "..", "c") 171 result = opts.TargetPath() 172 assert.Equal(t, expected, result) 173 174 // absolute target, server path 175 opts = new(GenOpts) 176 _ = opts.EnsureDefaults() 177 opts.Target = filepath.Join(cwd, "a", "b", "c") 178 opts.ServerPackage = path.Join("y", "z") 179 expected = filepath.Join("..", "..", "..", "c") 180 result = opts.TargetPath() 181 assert.Equal(t, expected, result) 182 } 183 184 // NOTE: file://url is not supported 185 func TestShared_SpecPath(t *testing.T) { 186 defer discardOutput()() 187 188 cwd, _ := os.Getwd() 189 190 // http URL spec 191 opts := new(GenOpts) 192 _ = opts.EnsureDefaults() 193 opts.Spec = "http://a/b/c" 194 opts.ServerPackage = "y" 195 expected := opts.Spec 196 result := opts.SpecPath() 197 assert.Equal(t, expected, result) 198 199 // https URL spec 200 opts = new(GenOpts) 201 _ = opts.EnsureDefaults() 202 opts.Spec = "https://a/b/c" 203 opts.ServerPackage = "y" 204 expected = opts.Spec 205 result = opts.SpecPath() 206 assert.Equal(t, expected, result) 207 208 // relative spec 209 opts = new(GenOpts) 210 _ = opts.EnsureDefaults() 211 opts.Spec = filepath.Join(".", "a", "b", "c") 212 opts.Target = "d" 213 opts.ServerPackage = "y" 214 expected = filepath.Join("..", "..", "a", "b", "c") 215 result = opts.SpecPath() 216 assert.Equal(t, expected, result) 217 218 // relative spec, server path 219 opts = new(GenOpts) 220 _ = opts.EnsureDefaults() 221 opts.Spec = filepath.Join(".", "a", "b", "c") 222 opts.Target = filepath.Join("d", "e") 223 opts.ServerPackage = "y/z" 224 expected = filepath.Join("..", "..", "..", "..", "a", "b", "c") 225 result = opts.SpecPath() 226 assert.Equal(t, expected, result) 227 228 // relative spec, server path 229 opts = new(GenOpts) 230 _ = opts.EnsureDefaults() 231 opts.Spec = filepath.Join(".", "a", "b", "c") 232 opts.Target = filepath.Join(".", "a", "b") 233 opts.ServerPackage = "y/z" 234 expected = filepath.Join("..", "..", "c") 235 result = opts.SpecPath() 236 assert.Equal(t, expected, result) 237 238 // absolute spec 239 opts = new(GenOpts) 240 _ = opts.EnsureDefaults() 241 opts.Spec = filepath.Join(cwd, "a", "b", "c") 242 opts.ServerPackage = "y" 243 expected = filepath.Join("..", "a", "b", "c") 244 result = opts.SpecPath() 245 assert.Equal(t, expected, result) 246 247 // absolute spec, server path 248 opts = new(GenOpts) 249 _ = opts.EnsureDefaults() 250 opts.Spec = filepath.Join("..", "a", "b", "c") 251 opts.Target = "" 252 opts.ServerPackage = path.Join("y", "z") 253 expected = filepath.Join("..", "..", "..", "a", "b", "c") 254 result = opts.SpecPath() 255 assert.Equal(t, expected, result) 256 257 if runtime.GOOS == "windows" { 258 opts = new(GenOpts) 259 _ = opts.EnsureDefaults() 260 opts.Spec = filepath.Join("a", "b", "c") 261 opts.Target = filepath.Join("Z:", "e", "f", "f") 262 opts.ServerPackage = "y/z" 263 expected, _ = filepath.Abs(opts.Spec) 264 result = opts.SpecPath() 265 assert.Equal(t, expected, result) 266 } 267 } 268 269 // Low level testing: templates not found (higher level calls raise panic(), see above) 270 func TestShared_NotFoundTemplate(t *testing.T) { 271 defer discardOutput()() 272 273 opts := testGenOpts() 274 tplOpts := TemplateOpts{ 275 Name: "NotFound", 276 Source: "asset:notfound", 277 Target: ".", 278 FileName: "test_notfound.go", 279 SkipExists: false, 280 SkipFormat: false, 281 } 282 283 buf, err := opts.render(&tplOpts, nil) 284 require.Errorf(t, err, "Error should be handled here") 285 assert.Nilf(t, buf, "Upon error, GenOpts.render() should return nil buffer") 286 } 287 288 // Low level testing: invalid template => Get() returns not found (higher level calls raise panic(), see above) 289 // TODO: better error discrimination between absent definition and non-parsing template 290 func TestShared_GarbledTemplate(t *testing.T) { 291 defer discardOutput()() 292 293 garbled := "func x {{;;; garbled" 294 295 _ = templates.AddFile("garbled", garbled) 296 opts := testGenOpts() 297 298 tplOpts := TemplateOpts{ 299 Name: "Garbled", 300 Source: "asset:garbled", 301 Target: ".", 302 FileName: "test_garbled.go", 303 SkipExists: false, 304 SkipFormat: false, 305 } 306 307 buf, err := opts.render(&tplOpts, nil) 308 require.Errorf(t, err, "Error should be handled here") 309 assert.Nilf(t, buf, "Upon error, GenOpts.render() should return nil buffer") 310 } 311 312 // Template execution failure 313 type myTemplateData struct{} 314 315 func (*myTemplateData) MyFaultyMethod() (string, error) { 316 return "", fmt.Errorf("myFaultyError") 317 } 318 319 func TestShared_ExecTemplate(t *testing.T) { 320 defer discardOutput()() 321 322 // Not a failure: no value data 323 execfailure1 := "func x {{ .NotInData }}" 324 325 _ = templates.AddFile("execfailure1", execfailure1) 326 opts := testGenOpts() 327 328 tplOpts := TemplateOpts{ 329 Name: "execFailure1", 330 Source: "asset:execfailure1", 331 Target: ".", 332 FileName: "test_execfailure1.go", 333 SkipExists: false, 334 SkipFormat: false, 335 } 336 337 buf1, err := opts.render(&tplOpts, nil) 338 require.NoError(t, err, "Template rendering should put <no value> instead of missing data, and report no error") 339 assert.Equal(t, "func x <no value>", string(buf1)) 340 341 execfailure2 := "func {{ .MyFaultyMethod }}" 342 343 _ = templates.AddFile("execfailure2", execfailure2) 344 opts = testGenOpts() 345 tplOpts2 := TemplateOpts{ 346 Name: "execFailure2", 347 Source: "asset:execfailure2", 348 Target: ".", 349 FileName: "test_execfailure2.go", 350 SkipExists: false, 351 SkipFormat: false, 352 } 353 354 data := new(myTemplateData) 355 buf2, err := opts.render(&tplOpts2, data) 356 require.Error(t, err, "Error should be handled here: missing func in template yields an error") 357 assert.Contains(t, err.Error(), "template execution failed") 358 assert.Nil(t, buf2, "Upon error, GenOpts.render() should return nil buffer") 359 } 360 361 // Test correctly parsed templates, with bad formatting 362 func TestShared_BadFormatTemplate(t *testing.T) { 363 // TODO: fred refact 364 defer discardOutput()() 365 366 t.Cleanup(func() { 367 _ = os.Remove("test_badformat.gol") 368 _ = os.Remove("test_badformat2.gol") 369 Debug = false 370 }) 371 372 // Not skipping format 373 badFormat := "func x {;;; garbled" 374 375 Debug = true 376 _ = templates.AddFile("badformat", badFormat) 377 378 opts := testGenOpts() 379 opts.LanguageOpts = GoLangOpts() 380 tplOpts := TemplateOpts{ 381 Name: "badformat", 382 Source: "asset:badformat", 383 Target: ".", 384 // Extension ".gol" won't mess with go if cleanup is not performed 385 FileName: "test_badformat.gol", 386 SkipExists: false, 387 SkipFormat: false, 388 } 389 390 data := appGenerator{ 391 Name: "badtest", 392 Package: "wrongpkg", 393 } 394 395 err := opts.write(&tplOpts, data) 396 defer func() { 397 _ = os.Remove(tplOpts.FileName) 398 }() 399 400 // The badly formatted file has been dumped for debugging purposes 401 _, exists := os.Stat(tplOpts.FileName) 402 assert.False(t, os.IsNotExist(exists), "The template file has not been generated as expected") 403 404 require.Error(t, err) 405 assert.Contains(t, err.Error(), "source formatting on generated source") 406 407 // Skipping format 408 opts = testGenOpts() 409 opts.LanguageOpts = GoLangOpts() 410 tplOpts2 := TemplateOpts{ 411 Name: "badformat2", 412 Source: "asset:badformat", 413 Target: ".", 414 FileName: "test_badformat2.gol", 415 SkipExists: false, 416 SkipFormat: true, 417 } 418 419 err2 := opts.write(&tplOpts2, data) 420 421 // The unformatted file has been dumped without format checks 422 _, exists2 := os.Stat(tplOpts2.FileName) 423 assert.False(t, os.IsNotExist(exists2), "The template file has not been generated as expected") 424 _ = os.Remove(tplOpts2.FileName) 425 426 require.NoError(t, err2) 427 428 // os.RemoveAll(filepath.Join(filepath.FromSlash(dr),"restapi")) 429 } 430 431 // Test dir creation 432 func TestShared_DirectoryTemplate(t *testing.T) { 433 defer discardOutput()() 434 435 t.Cleanup(func() { 436 _ = os.RemoveAll("TestGenDir") 437 }) 438 439 // Not skipping format 440 content := "func x {}" 441 442 _ = templates.AddFile("gendir", content) 443 444 opts := testGenOpts() 445 opts.LanguageOpts = GoLangOpts() 446 tplOpts := TemplateOpts{ 447 Name: "gendir", 448 Source: "asset:gendir", 449 Target: "TestGenDir", 450 // Extension ".gol" won't mess with go if cleanup is not performed 451 FileName: "test_gendir.gol", 452 SkipExists: false, 453 SkipFormat: true, 454 } 455 456 data := appGenerator{ 457 Name: "gentest", 458 Package: "stubpkg", 459 } 460 461 err := opts.write(&tplOpts, data) 462 463 // The badly formatted file has been dumped for debugging purposes 464 _, exists := os.Stat(filepath.Join(tplOpts.Target, tplOpts.FileName)) 465 assert.False(t, os.IsNotExist(exists), "The template file has not been generated as expected") 466 _ = os.RemoveAll(tplOpts.Target) 467 468 require.NoError(t, err) 469 } 470 471 // Test templates which are not assets (open in file) 472 // Low level testing: templates loaded from file 473 func TestShared_LoadTemplate(t *testing.T) { 474 defer discardOutput()() 475 476 opts := testGenOpts() 477 tplOpts := TemplateOpts{ 478 Name: "File", 479 Source: "File", 480 Target: ".", 481 FileName: "file.go", 482 SkipExists: false, 483 SkipFormat: false, 484 } 485 486 buf, err := opts.render(&tplOpts, nil) 487 require.Error(t, err, "Error should be handled here") 488 assert.Contains(t, err.Error(), "open File") 489 assert.Contains(t, err.Error(), "error while opening") 490 assert.Nil(t, buf, "Upon error, GenOpts.render() should return nil buffer") 491 492 opts.TemplateDir = filepath.Join(".", "myTemplateDir") 493 buf, err = opts.render(&tplOpts, nil) 494 require.Error(t, err, "Error should be handled here") 495 assert.Contains(t, err.Error(), "open "+filepath.Join("myTemplateDir", "File")) 496 assert.Contains(t, err.Error(), "error while opening") 497 assert.Nil(t, buf, "Upon error, GenOpts.render() should return nil buffer") 498 } 499 500 func TestShared_AppNameOrDefault(t *testing.T) { 501 specPath := filepath.Join("..", "fixtures", "codegen", "shipyard.yml") 502 specDoc, err := loads.Spec(specPath) 503 require.NoError(t, err) 504 505 require.NotNil(t, specDoc.Spec().Info) 506 specDoc.Spec().Info.Title = " " 507 assert.Equal(t, "Xyz", appNameOrDefault(specDoc, " ", "xyz")) 508 specDoc.Spec().Info.Title = "test" 509 assert.Equal(t, "Xyz", appNameOrDefault(specDoc, " ", "xyz")) 510 511 opts := testGenOpts() 512 opts.Spec = specPath 513 _, err = opts.validateAndFlattenSpec() 514 require.NoError(t, err) 515 516 // more aggressive fixture on $refs, with validation errors, but flatten ok 517 specPath = filepath.Join("..", "fixtures", "bugs", "1429", "swagger.yaml") 518 specDoc, err = loads.Spec(specPath) 519 require.NoError(t, err) 520 521 opts.Spec = specPath 522 opts.FlattenOpts.BasePath = specDoc.SpecFilePath() 523 opts.FlattenOpts.Spec = analysis.New(specDoc.Spec()) 524 opts.FlattenOpts.Minimal = true 525 err = analysis.Flatten(*opts.FlattenOpts) 526 require.NoError(t, err) 527 528 specDoc, _ = loads.Spec(specPath) // needs reload 529 opts.FlattenOpts.Spec = analysis.New(specDoc.Spec()) 530 opts.FlattenOpts.Minimal = false 531 err = analysis.Flatten(*opts.FlattenOpts) 532 require.NoError(t, err) 533 } 534 535 func TestShared_GatherModel(t *testing.T) { 536 specPath := filepath.Join("..", "fixtures", "codegen", "shipyard.yml") 537 538 specDoc, err := loads.Spec(specPath) 539 require.NoError(t, err) 540 541 _, err = gatherModels(specDoc, []string{"unknown"}) 542 require.Error(t, err) 543 544 res, err := gatherModels(specDoc, []string{"Image", "Application"}) 545 require.NoError(t, err) 546 assert.Len(t, res, 2) 547 548 res, err = gatherModels(specDoc, []string{"Image", "Application"}) 549 require.NoError(t, err) 550 assert.Len(t, res, 2) 551 552 res, err = gatherModels(specDoc, []string{}) 553 require.NoError(t, err) 554 assert.Len(t, res, 4) 555 } 556 557 func TestShared_DumpWrongData(t *testing.T) { 558 defer discardOutput()() 559 560 t.Run("should not be able to dump things that don't marshal as JSON", func(t *testing.T) { 561 require.Error(t, dumpData(struct { 562 A func() string 563 B string 564 }{ 565 A: func() string { return "" }, 566 B: "xyz", 567 })) 568 }) 569 570 t.Run("should dump any data, with unmarshallable fields exlicitly excluded", func(t *testing.T) { 571 require.NoError(t, dumpData(struct { 572 A func() string `json:"-"` 573 B string 574 }{ 575 A: func() string { return "" }, 576 B: "xyz", 577 })) 578 579 require.NoError(t, dumpData(struct { 580 a func() string 581 B string 582 }{ 583 a: func() string { return "" }, 584 B: "xyz", 585 })) 586 }) 587 } 588 589 func TestResolvePrincipal(t *testing.T) { 590 for _, toPin := range []struct { 591 Title string 592 Principal string 593 Expected []string 594 }{ 595 { 596 Title: "defaults", Principal: "", 597 Expected: []string{"", "interface{}", ""}, 598 }, 599 { 600 Title: "with base import", Principal: "auth.Principal", 601 Expected: []string{"auth", "auth.Principal", "auth"}, 602 }, 603 { 604 Title: "with full import", Principal: "github.com/myproject/auth.Principal", 605 Expected: []string{"auth", "auth.Principal", "github.com/myproject/auth"}, 606 }, 607 { 608 Title: "with name conflict", Principal: "github.com/myproject/middleware.Principal", 609 Expected: []string{"auth", "auth.Principal", "github.com/myproject/middleware"}, 610 }, 611 { 612 Title: "with name conflict (2)", Principal: "github.com/myproject/principal.Principal", 613 Expected: []string{"auth", "auth.Principal", "github.com/myproject/principal"}, 614 }, 615 } { 616 fixture := toPin 617 t.Run(fixture.Title, func(t *testing.T) { 618 t.Parallel() 619 opts := &GenOpts{GenOptsCommon: GenOptsCommon{Principal: fixture.Principal}} 620 err := opts.EnsureDefaults() 621 require.NoError(t, err) 622 alias, principal, target := opts.resolvePrincipal() 623 require.Equal(t, fixture.Expected[0], alias) 624 require.Equal(t, fixture.Expected[1], principal) 625 require.Equal(t, fixture.Expected[2], target) 626 }) 627 } 628 } 629 630 func TestDefaultImports(t *testing.T) { 631 for i, toPin := range []struct { 632 Title string 633 Opts *GenOpts 634 Expected map[string]string 635 }{ 636 { 637 Title: "defaults", 638 Opts: &GenOpts{}, 639 Expected: map[string]string{ 640 "models": "github.com/go-swagger/go-swagger/generator/models", 641 }, 642 }, 643 { 644 Title: "with base import", 645 Opts: &GenOpts{ 646 GenOptsCommon: GenOptsCommon{ 647 Principal: "ext.Principal", 648 }, 649 }, 650 Expected: map[string]string{ 651 "ext": "github.com/go-swagger/go-swagger/generator/ext", 652 "models": "github.com/go-swagger/go-swagger/generator/models", 653 }, 654 }, 655 { 656 Title: "with full import", 657 Opts: &GenOpts{ 658 GenOptsCommon: GenOptsCommon{ 659 Principal: "github.com/myproject/identity.Principal", 660 }, 661 }, 662 Expected: map[string]string{ 663 "identity": "github.com/myproject/identity", 664 "models": "github.com/go-swagger/go-swagger/generator/models", 665 }, 666 }, 667 { 668 Title: "with name conflict", 669 Opts: &GenOpts{ 670 GenOptsCommon: GenOptsCommon{ 671 Principal: "github.com/myproject/middleware.Principal", 672 }, 673 }, 674 Expected: map[string]string{ 675 "auth": "github.com/myproject/middleware", 676 "models": "github.com/go-swagger/go-swagger/generator/models", 677 }, 678 }, 679 { 680 Title: "with name conflict (2)", 681 Opts: &GenOpts{ 682 GenOptsCommon: GenOptsCommon{ 683 Principal: "github.com/myproject/principal.Principal", 684 }, 685 }, 686 Expected: map[string]string{ 687 "auth": "github.com/myproject/principal", 688 "models": "github.com/go-swagger/go-swagger/generator/models", 689 }, 690 }, 691 { 692 Title: "alternate target for models", 693 Opts: &GenOpts{ 694 GenOptsCommon: GenOptsCommon{ 695 ModelPackage: "target/bespoke", 696 }, 697 }, 698 Expected: map[string]string{ 699 "bespoke": "github.com/go-swagger/go-swagger/generator/target/bespoke", 700 }, 701 }, 702 { 703 Title: "with existing models", 704 Opts: &GenOpts{ 705 GenOptsCommon: GenOptsCommon{ 706 ExistingModels: "github.com/myproject/target/bespoke", 707 }, 708 }, 709 Expected: map[string]string{ 710 "models": "github.com/myproject/target/bespoke", 711 }, 712 }, 713 // issue #2362 714 { 715 Title: "relative principal, in dedicated package under generated target", 716 Opts: &GenOpts{ 717 GenOptsCommon: GenOptsCommon{ 718 Principal: "auth.Principal", 719 ModelPackage: "target/bespoke", 720 }, 721 }, 722 Expected: map[string]string{ 723 "bespoke": "github.com/go-swagger/go-swagger/generator/target/bespoke", 724 "auth": "github.com/go-swagger/go-swagger/generator/auth", 725 }, 726 }, 727 { 728 Title: "relative principal in models (1)", 729 Opts: &GenOpts{ 730 GenOptsCommon: GenOptsCommon{ 731 Principal: "bespoke.Principal", 732 ModelPackage: "target/bespoke", 733 }, 734 }, 735 Expected: map[string]string{ 736 "bespoke": "github.com/go-swagger/go-swagger/generator/target/bespoke", 737 }, 738 }, 739 { 740 Title: "relative principal in models (2)", 741 Opts: &GenOpts{ 742 GenOptsCommon: GenOptsCommon{ 743 Principal: "target/bespoke.Principal", 744 ModelPackage: "target/bespoke", 745 }, 746 }, 747 Expected: map[string]string{ 748 "bespoke": "github.com/go-swagger/go-swagger/generator/target/bespoke", 749 }, 750 }, 751 { 752 Title: "relative principal: not detected", 753 // NOTE: this case will probably not build: no way to determine the user intent 754 Opts: &GenOpts{ 755 GenOptsCommon: GenOptsCommon{ 756 Principal: "target/auth.Principal", 757 ModelPackage: "target/models", 758 }, 759 }, 760 Expected: map[string]string{ 761 "models": "github.com/go-swagger/go-swagger/generator/target/models", 762 "auth": "target/auth", 763 }, 764 }, 765 } { 766 fixture := toPin 767 i := i 768 t.Run(fixture.Title, func(t *testing.T) { 769 t.Parallel() 770 err := fixture.Opts.EnsureDefaults() 771 require.NoError(t, err) 772 imports := fixture.Opts.defaultImports() 773 require.EqualValuesf(t, fixture.Expected, imports, "unexpected imports generated with fixture %q[%d]", fixture.Title, i) 774 }) 775 } 776 } 777 778 func TestShared_Issue2113(t *testing.T) { 779 defer discardOutput()() 780 781 // acknowledge fix in go-openapi/spec 782 specPath := filepath.Join("..", "fixtures", "bugs", "2113", "base.yaml") 783 _, err := loads.Spec(specPath) 784 require.NoError(t, err) 785 786 opts := testGenOpts() 787 opts.Spec = specPath 788 opts.ValidateSpec = true 789 _, err = opts.validateAndFlattenSpec() 790 require.NoError(t, err) 791 } 792 793 func TestShared_Issue2743(t *testing.T) { 794 defer discardOutput()() 795 796 // acknowledge fix in go-openapi/spec 797 t.Run("should NOT flatten invalid spec that used to work", func(t *testing.T) { 798 specPath := filepath.Join("..", "fixtures", "bugs", "2743", "working", "spec.yaml") 799 _, err := loads.Spec(specPath) 800 require.NoError(t, err) 801 802 opts := testGenOpts() 803 opts.Spec = specPath 804 opts.ValidateSpec = true 805 _, err = opts.validateAndFlattenSpec() 806 require.Error(t, err) 807 }) 808 809 t.Run("should flatten valid spec that used NOT to work", func(t *testing.T) { 810 specPath := filepath.Join("..", "fixtures", "bugs", "2743", "not-working", "spec.yaml") 811 _, err := loads.Spec(specPath) 812 require.NoError(t, err) 813 814 opts := testGenOpts() 815 opts.Spec = specPath 816 opts.ValidateSpec = true 817 _, err = opts.validateAndFlattenSpec() 818 require.NoError(t, err) 819 }) 820 }