github.com/thetreep/go-swagger@v0.0.0-20240223100711-35af64f14f01/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( 367 func() { 368 _ = os.Remove("test_badformat.gol") 369 _ = os.Remove("test_badformat2.gol") 370 Debug = false 371 }, 372 ) 373 374 // Not skipping format 375 badFormat := "func x {;;; garbled" 376 377 Debug = true 378 _ = templates.AddFile("badformat", badFormat) 379 380 opts := testGenOpts() 381 opts.LanguageOpts = GoLangOpts() 382 tplOpts := TemplateOpts{ 383 Name: "badformat", 384 Source: "asset:badformat", 385 Target: ".", 386 // Extension ".gol" won't mess with go if cleanup is not performed 387 FileName: "test_badformat.gol", 388 SkipExists: false, 389 SkipFormat: false, 390 } 391 392 data := appGenerator{ 393 Name: "badtest", 394 Package: "wrongpkg", 395 } 396 397 err := opts.write(&tplOpts, data) 398 defer func() { 399 _ = os.Remove(tplOpts.FileName) 400 }() 401 402 // The badly formatted file has been dumped for debugging purposes 403 _, exists := os.Stat(tplOpts.FileName) 404 assert.False(t, os.IsNotExist(exists), "The template file has not been generated as expected") 405 406 require.Error(t, err) 407 assert.Contains(t, err.Error(), "source formatting on generated source") 408 409 // Skipping format 410 opts = testGenOpts() 411 opts.LanguageOpts = GoLangOpts() 412 tplOpts2 := TemplateOpts{ 413 Name: "badformat2", 414 Source: "asset:badformat", 415 Target: ".", 416 FileName: "test_badformat2.gol", 417 SkipExists: false, 418 SkipFormat: true, 419 } 420 421 err2 := opts.write(&tplOpts2, data) 422 423 // The unformatted file has been dumped without format checks 424 _, exists2 := os.Stat(tplOpts2.FileName) 425 assert.False(t, os.IsNotExist(exists2), "The template file has not been generated as expected") 426 _ = os.Remove(tplOpts2.FileName) 427 428 require.NoError(t, err2) 429 430 // os.RemoveAll(filepath.Join(filepath.FromSlash(dr),"restapi")) 431 } 432 433 // Test dir creation 434 func TestShared_DirectoryTemplate(t *testing.T) { 435 defer discardOutput()() 436 437 t.Cleanup( 438 func() { 439 _ = os.RemoveAll("TestGenDir") 440 }, 441 ) 442 443 // Not skipping format 444 content := "func x {}" 445 446 _ = templates.AddFile("gendir", content) 447 448 opts := testGenOpts() 449 opts.LanguageOpts = GoLangOpts() 450 tplOpts := TemplateOpts{ 451 Name: "gendir", 452 Source: "asset:gendir", 453 Target: "TestGenDir", 454 // Extension ".gol" won't mess with go if cleanup is not performed 455 FileName: "test_gendir.gol", 456 SkipExists: false, 457 SkipFormat: true, 458 } 459 460 data := appGenerator{ 461 Name: "gentest", 462 Package: "stubpkg", 463 } 464 465 err := opts.write(&tplOpts, data) 466 467 // The badly formatted file has been dumped for debugging purposes 468 _, exists := os.Stat(filepath.Join(tplOpts.Target, tplOpts.FileName)) 469 assert.False(t, os.IsNotExist(exists), "The template file has not been generated as expected") 470 _ = os.RemoveAll(tplOpts.Target) 471 472 require.NoError(t, err) 473 } 474 475 // Test templates which are not assets (open in file) 476 // Low level testing: templates loaded from file 477 func TestShared_LoadTemplate(t *testing.T) { 478 defer discardOutput()() 479 480 opts := testGenOpts() 481 tplOpts := TemplateOpts{ 482 Name: "File", 483 Source: "File", 484 Target: ".", 485 FileName: "file.go", 486 SkipExists: false, 487 SkipFormat: false, 488 } 489 490 buf, err := opts.render(&tplOpts, nil) 491 require.Error(t, err, "Error should be handled here") 492 assert.Contains(t, err.Error(), "open File") 493 assert.Contains(t, err.Error(), "error while opening") 494 assert.Nil(t, buf, "Upon error, GenOpts.render() should return nil buffer") 495 496 opts.TemplateDir = filepath.Join(".", "myTemplateDir") 497 buf, err = opts.render(&tplOpts, nil) 498 require.Error(t, err, "Error should be handled here") 499 assert.Contains(t, err.Error(), "open "+filepath.Join("myTemplateDir", "File")) 500 assert.Contains(t, err.Error(), "error while opening") 501 assert.Nil(t, buf, "Upon error, GenOpts.render() should return nil buffer") 502 } 503 504 func TestShared_AppNameOrDefault(t *testing.T) { 505 specPath := filepath.Join("..", "fixtures", "codegen", "shipyard.yml") 506 specDoc, err := loads.Spec(specPath) 507 require.NoError(t, err) 508 509 require.NotNil(t, specDoc.Spec().Info) 510 specDoc.Spec().Info.Title = " " 511 assert.Equal(t, "Xyz", appNameOrDefault(specDoc, " ", "xyz")) 512 specDoc.Spec().Info.Title = "test" 513 assert.Equal(t, "Xyz", appNameOrDefault(specDoc, " ", "xyz")) 514 515 opts := testGenOpts() 516 opts.Spec = specPath 517 _, err = opts.validateAndFlattenSpec() 518 require.NoError(t, err) 519 520 // more aggressive fixture on $refs, with validation errors, but flatten ok 521 specPath = filepath.Join("..", "fixtures", "bugs", "1429", "swagger.yaml") 522 specDoc, err = loads.Spec(specPath) 523 require.NoError(t, err) 524 525 opts.Spec = specPath 526 opts.FlattenOpts.BasePath = specDoc.SpecFilePath() 527 opts.FlattenOpts.Spec = analysis.New(specDoc.Spec()) 528 opts.FlattenOpts.Minimal = true 529 err = analysis.Flatten(*opts.FlattenOpts) 530 require.NoError(t, err) 531 532 specDoc, _ = loads.Spec(specPath) // needs reload 533 opts.FlattenOpts.Spec = analysis.New(specDoc.Spec()) 534 opts.FlattenOpts.Minimal = false 535 err = analysis.Flatten(*opts.FlattenOpts) 536 require.NoError(t, err) 537 } 538 539 func TestShared_GatherModel(t *testing.T) { 540 specPath := filepath.Join("..", "fixtures", "codegen", "shipyard.yml") 541 542 specDoc, err := loads.Spec(specPath) 543 require.NoError(t, err) 544 545 _, err = gatherModels(specDoc, []string{"unknown"}) 546 require.Error(t, err) 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{"Image", "Application"}) 553 require.NoError(t, err) 554 assert.Len(t, res, 2) 555 556 res, err = gatherModels(specDoc, []string{}) 557 require.NoError(t, err) 558 assert.Len(t, res, 4) 559 } 560 561 func TestShared_DumpWrongData(t *testing.T) { 562 defer discardOutput()() 563 564 t.Run( 565 "should not be able to dump things that don't marshal as JSON", func(t *testing.T) { 566 require.Error( 567 t, dumpData( 568 struct { 569 A func() string 570 B string 571 }{ 572 A: func() string { return "" }, 573 B: "xyz", 574 }, 575 ), 576 ) 577 }, 578 ) 579 580 t.Run( 581 "should dump any data, with unmarshallable fields exlicitly excluded", func(t *testing.T) { 582 require.NoError( 583 t, dumpData( 584 struct { 585 A func() string `json:"-"` 586 B string 587 }{ 588 A: func() string { return "" }, 589 B: "xyz", 590 }, 591 ), 592 ) 593 594 require.NoError( 595 t, dumpData( 596 struct { 597 a func() string 598 B string 599 }{ 600 a: func() string { return "" }, 601 B: "xyz", 602 }, 603 ), 604 ) 605 }, 606 ) 607 } 608 609 func TestResolvePrincipal(t *testing.T) { 610 for _, toPin := range []struct { 611 Title string 612 Principal string 613 Expected []string 614 }{ 615 { 616 Title: "defaults", Principal: "", 617 Expected: []string{"", "interface{}", ""}, 618 }, 619 { 620 Title: "with base import", Principal: "auth.Principal", 621 Expected: []string{"auth", "auth.Principal", "auth"}, 622 }, 623 { 624 Title: "with full import", Principal: "github.com/myproject/auth.Principal", 625 Expected: []string{"auth", "auth.Principal", "github.com/myproject/auth"}, 626 }, 627 { 628 Title: "with name conflict", Principal: "github.com/myproject/middleware.Principal", 629 Expected: []string{"auth", "auth.Principal", "github.com/myproject/middleware"}, 630 }, 631 { 632 Title: "with name conflict (2)", Principal: "github.com/myproject/principal.Principal", 633 Expected: []string{"auth", "auth.Principal", "github.com/myproject/principal"}, 634 }, 635 } { 636 fixture := toPin 637 t.Run( 638 fixture.Title, func(t *testing.T) { 639 t.Parallel() 640 opts := &GenOpts{GenOptsCommon: GenOptsCommon{Principal: fixture.Principal}} 641 err := opts.EnsureDefaults() 642 require.NoError(t, err) 643 alias, principal, target := opts.resolvePrincipal() 644 require.Equal(t, fixture.Expected[0], alias) 645 require.Equal(t, fixture.Expected[1], principal) 646 require.Equal(t, fixture.Expected[2], target) 647 }, 648 ) 649 } 650 } 651 652 func TestDefaultImports(t *testing.T) { 653 for i, toPin := range []struct { 654 Title string 655 Opts *GenOpts 656 Expected map[string]string 657 }{ 658 { 659 Title: "defaults", 660 Opts: &GenOpts{}, 661 Expected: map[string]string{ 662 "models": "github.com/thetreep/go-swagger/generator/models", 663 }, 664 }, 665 { 666 Title: "with base import", 667 Opts: &GenOpts{ 668 GenOptsCommon: GenOptsCommon{ 669 Principal: "ext.Principal", 670 }, 671 }, 672 Expected: map[string]string{ 673 "ext": "github.com/thetreep/go-swagger/generator/ext", 674 "models": "github.com/thetreep/go-swagger/generator/models", 675 }, 676 }, 677 { 678 Title: "with full import", 679 Opts: &GenOpts{ 680 GenOptsCommon: GenOptsCommon{ 681 Principal: "github.com/myproject/identity.Principal", 682 }, 683 }, 684 Expected: map[string]string{ 685 "identity": "github.com/myproject/identity", 686 "models": "github.com/thetreep/go-swagger/generator/models", 687 }, 688 }, 689 { 690 Title: "with name conflict", 691 Opts: &GenOpts{ 692 GenOptsCommon: GenOptsCommon{ 693 Principal: "github.com/myproject/middleware.Principal", 694 }, 695 }, 696 Expected: map[string]string{ 697 "auth": "github.com/myproject/middleware", 698 "models": "github.com/thetreep/go-swagger/generator/models", 699 }, 700 }, 701 { 702 Title: "with name conflict (2)", 703 Opts: &GenOpts{ 704 GenOptsCommon: GenOptsCommon{ 705 Principal: "github.com/myproject/principal.Principal", 706 }, 707 }, 708 Expected: map[string]string{ 709 "auth": "github.com/myproject/principal", 710 "models": "github.com/thetreep/go-swagger/generator/models", 711 }, 712 }, 713 { 714 Title: "alternate target for models", 715 Opts: &GenOpts{ 716 GenOptsCommon: GenOptsCommon{ 717 ModelPackage: "target/bespoke", 718 }, 719 }, 720 Expected: map[string]string{ 721 "bespoke": "github.com/thetreep/go-swagger/generator/target/bespoke", 722 }, 723 }, 724 { 725 Title: "with existing models", 726 Opts: &GenOpts{ 727 GenOptsCommon: GenOptsCommon{ 728 ExistingModels: "github.com/myproject/target/bespoke", 729 }, 730 }, 731 Expected: map[string]string{ 732 "models": "github.com/myproject/target/bespoke", 733 }, 734 }, 735 // issue #2362 736 { 737 Title: "relative principal, in dedicated package under generated target", 738 Opts: &GenOpts{ 739 GenOptsCommon: GenOptsCommon{ 740 Principal: "auth.Principal", 741 ModelPackage: "target/bespoke", 742 }, 743 }, 744 Expected: map[string]string{ 745 "bespoke": "github.com/thetreep/go-swagger/generator/target/bespoke", 746 "auth": "github.com/thetreep/go-swagger/generator/auth", 747 }, 748 }, 749 { 750 Title: "relative principal in models (1)", 751 Opts: &GenOpts{ 752 GenOptsCommon: GenOptsCommon{ 753 Principal: "bespoke.Principal", 754 ModelPackage: "target/bespoke", 755 }, 756 }, 757 Expected: map[string]string{ 758 "bespoke": "github.com/thetreep/go-swagger/generator/target/bespoke", 759 }, 760 }, 761 { 762 Title: "relative principal in models (2)", 763 Opts: &GenOpts{ 764 GenOptsCommon: GenOptsCommon{ 765 Principal: "target/bespoke.Principal", 766 ModelPackage: "target/bespoke", 767 }, 768 }, 769 Expected: map[string]string{ 770 "bespoke": "github.com/thetreep/go-swagger/generator/target/bespoke", 771 }, 772 }, 773 { 774 Title: "relative principal: not detected", 775 // NOTE: this case will probably not build: no way to determine the user intent 776 Opts: &GenOpts{ 777 GenOptsCommon: GenOptsCommon{ 778 Principal: "target/auth.Principal", 779 ModelPackage: "target/models", 780 }, 781 }, 782 Expected: map[string]string{ 783 "models": "github.com/thetreep/go-swagger/generator/target/models", 784 "auth": "target/auth", 785 }, 786 }, 787 } { 788 fixture := toPin 789 i := i 790 t.Run( 791 fixture.Title, func(t *testing.T) { 792 t.Parallel() 793 err := fixture.Opts.EnsureDefaults() 794 require.NoError(t, err) 795 imports := fixture.Opts.defaultImports() 796 require.EqualValuesf(t, fixture.Expected, imports, "unexpected imports generated with fixture %q[%d]", fixture.Title, i) 797 }, 798 ) 799 } 800 } 801 802 func TestShared_Issue2113(t *testing.T) { 803 defer discardOutput()() 804 805 // acknowledge fix in go-openapi/spec 806 specPath := filepath.Join("..", "fixtures", "bugs", "2113", "base.yaml") 807 _, err := loads.Spec(specPath) 808 require.NoError(t, err) 809 810 opts := testGenOpts() 811 opts.Spec = specPath 812 opts.ValidateSpec = true 813 _, err = opts.validateAndFlattenSpec() 814 require.NoError(t, err) 815 } 816 817 func TestShared_Issue2743(t *testing.T) { 818 defer discardOutput()() 819 820 // acknowledge fix in go-openapi/spec 821 t.Run( 822 "should NOT flatten invalid spec that used to work", func(t *testing.T) { 823 specPath := filepath.Join("..", "fixtures", "bugs", "2743", "working", "spec.yaml") 824 _, err := loads.Spec(specPath) 825 require.NoError(t, err) 826 827 opts := testGenOpts() 828 opts.Spec = specPath 829 opts.ValidateSpec = true 830 _, err = opts.validateAndFlattenSpec() 831 require.Error(t, err) 832 }, 833 ) 834 835 t.Run( 836 "should flatten valid spec that used NOT to work", func(t *testing.T) { 837 specPath := filepath.Join("..", "fixtures", "bugs", "2743", "not-working", "spec.yaml") 838 _, err := loads.Spec(specPath) 839 require.NoError(t, err) 840 841 opts := testGenOpts() 842 opts.Spec = specPath 843 opts.ValidateSpec = true 844 _, err = opts.validateAndFlattenSpec() 845 require.NoError(t, err) 846 }, 847 ) 848 }