github.com/go-swagger/go-swagger@v0.31.0/generator/generate_test.go (about)

     1  package generator
     2  
     3  import (
     4  	"bytes"
     5  	"fmt"
     6  	"io"
     7  	"os"
     8  	"path"
     9  	"path/filepath"
    10  	"runtime"
    11  	"strings"
    12  	"testing"
    13  
    14  	"github.com/stretchr/testify/assert"
    15  	"github.com/stretchr/testify/require"
    16  )
    17  
    18  func TestGenerateAndTest(t *testing.T) {
    19  	defer discardOutput()()
    20  
    21  	cwd := testCwd(t)
    22  	const root = "generated"
    23  	t.Cleanup(func() {
    24  		_ = os.RemoveAll(filepath.Join(cwd, root))
    25  	})
    26  
    27  	t.Run("server build", func(t *testing.T) {
    28  		for name, cas := range generateFixtures(t) {
    29  			thisCas := cas
    30  			thisName := name
    31  
    32  			t.Run(thisName, func(t *testing.T) {
    33  				t.Parallel()
    34  
    35  				defer thisCas.warnFailed(t)
    36  				opts := testGenOpts() // default opts
    37  
    38  				// create directory layout, defer clean
    39  				defer thisCas.prepareTarget(t, thisName, "server_test", root, opts)()
    40  
    41  				// preparation before generation
    42  				if thisCas.prepare != nil {
    43  					thisCas.prepare(t, opts)
    44  				}
    45  
    46  				t.Run(fmt.Sprintf("generating test server from %s", opts.Spec), func(t *testing.T) {
    47  					err := GenerateServer("", nil, nil, opts)
    48  					if thisCas.wantError {
    49  						require.Errorf(t, err, "expected an error for server build fixture: %s", opts.Spec)
    50  					} else {
    51  						require.NoError(t, err, "unexpected error for server build fixture: %s", opts.Spec)
    52  					}
    53  
    54  					// verify
    55  					if thisCas.verify != nil {
    56  						thisCas.verify(t, opts.Target)
    57  					}
    58  				})
    59  
    60  				// fixture-specific clean
    61  				if thisCas.clean != nil {
    62  					thisCas.clean()
    63  				}
    64  			})
    65  		}
    66  	})
    67  
    68  	t.Run("client build", func(t *testing.T) {
    69  		for name, cas := range generateClientFixtures(t) {
    70  			thisCas := cas
    71  			thisName := name
    72  
    73  			t.Run(thisName, func(t *testing.T) {
    74  				t.Parallel()
    75  
    76  				defer thisCas.warnFailed(t)
    77  				opts := testClientGenOpts() // default opts for client codegen
    78  
    79  				// create directory layout, defer clean
    80  				defer thisCas.prepareTarget(t, thisName, "server_test", root, opts)()
    81  
    82  				// preparation before generation
    83  				if thisCas.prepare != nil {
    84  					thisCas.prepare(t, opts)
    85  				}
    86  
    87  				t.Run(fmt.Sprintf("generating test client from %s", opts.Spec), func(t *testing.T) {
    88  					err := GenerateClient(thisName, nil, nil, opts)
    89  					if thisCas.wantError {
    90  						require.Errorf(t, err, "expected an error for client build fixture: %s", opts.Spec)
    91  					} else {
    92  						require.NoError(t, err, "unexpected error for client build fixture: %s", opts.Spec)
    93  					}
    94  
    95  					// verify
    96  					if thisCas.verify != nil {
    97  						thisCas.verify(t, opts.Target)
    98  					}
    99  				})
   100  
   101  				// fixture-specific clean
   102  				if thisCas.clean != nil {
   103  					thisCas.clean()
   104  				}
   105  			})
   106  		}
   107  	})
   108  }
   109  
   110  type generateFixture struct {
   111  	name      string
   112  	spec      string
   113  	target    string
   114  	wantError bool
   115  	prepare   func(*testing.T, *GenOpts)
   116  	verify    func(*testing.T, string)
   117  	clean     func()
   118  }
   119  
   120  func (f generateFixture) base(t testing.TB, root string) (string, func()) {
   121  	// base generation target
   122  	cwd := testCwd(t)
   123  
   124  	base := filepath.Join(cwd, root)
   125  	require.NoErrorf(t, os.MkdirAll(base, 0o700), "error in test creating target dir")
   126  
   127  	generated, err := os.MkdirTemp(base, "generated")
   128  	require.NoErrorf(t, err, "error in test creating temp dir")
   129  
   130  	return generated, func() {
   131  		_ = os.RemoveAll(generated)
   132  	}
   133  }
   134  
   135  func (f generateFixture) prepareTarget(t testing.TB, name, base, root string, opts *GenOpts) func() {
   136  	if name == "" {
   137  		name = f.name
   138  	}
   139  
   140  	spec := filepath.FromSlash(f.spec)
   141  	opts.Spec = spec
   142  
   143  	generated, clean := f.base(t, root)
   144  
   145  	if f.target == "" {
   146  		opts.Target = filepath.Join(generated, opts.LanguageOpts.ManglePackageName(name, base))
   147  	} else {
   148  		opts.Target = filepath.Join(generated, filepath.Base(f.target))
   149  	}
   150  
   151  	require.NoErrorf(t, os.MkdirAll(opts.Target, 0o700), "error in test creating target dir")
   152  
   153  	return clean
   154  }
   155  
   156  func (f generateFixture) warnFailed(t testing.TB) func() {
   157  	return func() {
   158  		if t.Failed() {
   159  			t.Log("ERROR: generation failed")
   160  		}
   161  	}
   162  }
   163  
   164  func generateFixtures(_ testing.TB) map[string]generateFixture {
   165  	return map[string]generateFixture{
   166  		"issue 1943": {
   167  			spec:   "../fixtures/bugs/1943/fixture-1943.yaml",
   168  			target: "../fixtures/bugs/1943",
   169  			prepare: func(t *testing.T, opts *GenOpts) {
   170  				input, err := os.ReadFile("../fixtures/bugs/1943/datarace_test.go")
   171  				require.NoError(t, err)
   172  
   173  				// rewrite imports for the relocated test program
   174  				cwd := testCwd(t)
   175  				rebased := bytes.ReplaceAll(
   176  					input,
   177  					[]byte("/fixtures/bugs/1943"),
   178  					[]byte(filepath.ToSlash(strings.TrimPrefix(opts.Target, filepath.Dir(cwd)))),
   179  				)
   180  
   181  				require.NoError(t, os.WriteFile(filepath.Join(opts.Target, "datarace_test.go"), rebased, 0o600))
   182  				opts.ExcludeSpec = false
   183  			},
   184  			verify: func(t *testing.T, target string) {
   185  				if runtime.GOOS == "windows" {
   186  					// don't run race tests on Appveyor CI
   187  					t.Logf("warn: race test skipped on windows")
   188  					return
   189  				}
   190  
   191  				const packages = "./..."
   192  				testPrg := "datarace_test.go"
   193  
   194  				t.Run("go get", goExecInDir(target, "get", packages))
   195  				t.Run("running data race test on generated server",
   196  					goExecInDir(target, "test", "-v", "-race", testPrg),
   197  				)
   198  			},
   199  		},
   200  		"packages_mangling": {
   201  			spec: "../fixtures/bugs/2111/fixture-2111.yaml",
   202  			prepare: func(_ *testing.T, opts *GenOpts) {
   203  				opts.IncludeMain = true
   204  			},
   205  			verify: func(t *testing.T, target string) {
   206  				require.True(t, fileExists(target, defaultServerTarget))
   207  				assert.True(t, fileExists(filepath.Join(target, "cmd", "unsafe-tag-names-server"), "main.go"))
   208  
   209  				srvTarget := filepath.Join(target, defaultServerTarget)
   210  				opsTarget := filepath.Join(srvTarget, defaultOperationsTarget)
   211  				require.True(t, fileExists(opsTarget, ""))
   212  
   213  				for _, fileOrDir := range []string{
   214  					"abc_linux", "abc_test",
   215  					"api",
   216  					"custom",
   217  					"hash_tag_donuts",
   218  					"nr123abc", "nr_at_donuts", "plus_donuts",
   219  					"strfmt",
   220  					"forced",
   221  					"gtl",
   222  					"nr12nasty",
   223  					"override",
   224  					"get_notag.go",
   225  					"operationsops",
   226  				} {
   227  					assert.True(t, fileExists(opsTarget, fileOrDir))
   228  				}
   229  
   230  				buf, err := os.ReadFile(filepath.Join(srvTarget, "configure_unsafe_tag_names.go"))
   231  				require.NoError(t, err)
   232  
   233  				code := string(buf)
   234  
   235  				// assert imports, with deconfliction
   236  				cwd := testCwd(t)
   237  				base := path.Join("github.com", "go-swagger", "go-swagger",
   238  					filepath.ToSlash(strings.TrimPrefix(target, filepath.Dir(cwd))),
   239  				)
   240  
   241  				baseImport := path.Join(base, `restapi/operations`)
   242  				assertImports(t, baseImport, code)
   243  
   244  				assertInCode(t, `api.APIGetConflictHandler = apiops.GetConflictHandlerFunc(`, code)
   245  				assertInCode(t, `api.StrfmtGetAnotherConflictHandler = strfmtops.GetAnotherConflictHandlerFunc(`, code)
   246  				assertInCode(t, `api.GetNotagHandler = operations.GetNotagHandlerFunc(`, code)
   247  
   248  				buf2, err := os.ReadFile(filepath.Join(opsTarget, "unsafe_tag_names_api.go"))
   249  				require.NoError(t, err)
   250  
   251  				api := string(buf2)
   252  				assertImports(t, baseImport, api)
   253  
   254  				assertInCode(t, `APIGetConflictHandler: apiops.GetConflictHandlerFunc(func(params apiops.GetConflictParams) middleware.Responder {`, api)
   255  				assertInCode(t, `StrfmtGetAnotherConflictHandler: strfmtops.GetAnotherConflictHandlerFunc(func(params strfmtops.GetAnotherConflictParams) middleware.Responder {`, api)
   256  				assertInCode(t, `GetNotagHandler: GetNotagHandlerFunc(func(params GetNotagParams) middleware.Responder {`, api)
   257  
   258  				assertInCode(t, `OverrideDeleteTestOverrideHandler override.DeleteTestOverrideHandler`, api)
   259  				assertInCode(t, `StrfmtGetAnotherConflictHandler strfmtops.GetAnotherConflictHandler`, api)
   260  				assertInCode(t, `APIGetConflictHandler apiops.GetConflictHandler`, api)
   261  				assertInCode(t, `CustomGetCustomHandler custom.GetCustomHandler`, api)
   262  				assertInCode(t, `AbcLinuxGetMultipleHandler abc_linux.GetMultipleHandler`, api)
   263  				assertInCode(t, `GetNotagHandler GetNotagHandler`, api)
   264  				assertInCode(t, `AbcLinuxGetOtherReservedHandler abc_linux.GetOtherReservedHandler`, api)
   265  				assertInCode(t, `PlusDonutsGetOtherUnsafeHandler plus_donuts.GetOtherUnsafeHandler`, api)
   266  				assertInCode(t, `AbcTestGetReservedHandler abc_test.GetReservedHandler`, api)
   267  				assertInCode(t, `GtlGetTestOverrideHandler gtl.GetTestOverrideHandler`, api)
   268  				assertInCode(t, `HashTagDonutsGetUnsafeHandler hash_tag_donuts.GetUnsafeHandler`, api)
   269  				assertInCode(t, `NrAtDonutsGetYetAnotherUnsafeHandler nr_at_donuts.GetYetAnotherUnsafeHandler`, api)
   270  				assertInCode(t, `ForcedPostTestOverrideHandler forced.PostTestOverrideHandler`, api)
   271  				assertInCode(t, `Nr12nastyPutTestOverrideHandler nr12nasty.PutTestOverrideHandler`, api)
   272  				assertInCode(t, `Nr123abcTestIDHandler nr123abc.TestIDHandler`, api)
   273  			},
   274  		},
   275  		"packages_flattening": {
   276  			spec: "../fixtures/bugs/2111/fixture-2111.yaml",
   277  			prepare: func(_ *testing.T, opts *GenOpts) {
   278  				opts.SkipTagPackages = true
   279  			},
   280  			verify: func(t *testing.T, target string) {
   281  				require.True(t, fileExists(target, defaultServerTarget))
   282  
   283  				srvTarget := filepath.Join(target, defaultServerTarget)
   284  				opsTarget := filepath.Join(srvTarget, defaultOperationsTarget)
   285  				require.True(t, fileExists(opsTarget, ""))
   286  
   287  				for _, fileOrDir := range []string{
   288  					"abc_linux", "abc_test",
   289  					"api",
   290  					"custom",
   291  					"hash_tag_donuts",
   292  					"nr123abc", "nr_at_donuts", "plus_donuts",
   293  					"strfmt",
   294  					"forced",
   295  					"gtl",
   296  					"nr12nasty",
   297  					"override",
   298  					"operationsops",
   299  				} {
   300  					assert.Falsef(t, fileExists(opsTarget, fileOrDir), "did not expect %s in %s", fileOrDir, opsTarget)
   301  				}
   302  
   303  				assert.Truef(t, fileExists(opsTarget, "get_notag.go"), "expected %s in %s", "get_notag.go", opsTarget)
   304  
   305  				buf, err := os.ReadFile(filepath.Join(srvTarget, "configure_unsafe_tag_names.go"))
   306  				require.NoError(t, err)
   307  				code := string(buf)
   308  
   309  				cwd := testCwd(t)
   310  				base := path.Join("github.com", "go-swagger", "go-swagger",
   311  					filepath.ToSlash(strings.TrimPrefix(target, filepath.Dir(cwd))),
   312  				)
   313  
   314  				baseImport := path.Join(base, `restapi/operations`)
   315  				assertRegexpInCode(t, baseImport, code)
   316  
   317  				assertInCode(t, `api.GetConflictHandler = operations.GetConflictHandlerFunc(`, code)
   318  				assertInCode(t, `api.GetAnotherConflictHandler = operations.GetAnotherConflictHandlerFunc(`, code)
   319  				assertInCode(t, `api.GetNotagHandler = operations.GetNotagHandlerFunc(`, code)
   320  
   321  				buf2, err := os.ReadFile(filepath.Join(opsTarget, "unsafe_tag_names_api.go"))
   322  				require.NoError(t, err)
   323  				api := string(buf2)
   324  
   325  				assertInCode(t, `GetConflictHandler: GetConflictHandlerFunc(func(params GetConflictParams) middleware.Responder {`, api)
   326  				assertInCode(t, `GetAnotherConflictHandler: GetAnotherConflictHandlerFunc(func(params GetAnotherConflictParams) middleware.Responder {`, api)
   327  				assertInCode(t, `NotagHandler: GetNotagHandlerFunc(func(params GetNotagParams) middleware.Responder {`, api)
   328  
   329  				assertInCode(t, `DeleteTestOverrideHandler DeleteTestOverrideHandler`, api)
   330  				assertInCode(t, `GetAnotherConflictHandler GetAnotherConflictHandler`, api)
   331  				assertInCode(t, `GetConflictHandler GetConflictHandler`, api)
   332  				assertInCode(t, `GetCustomHandler GetCustomHandler`, api)
   333  				assertInCode(t, `GetMultipleHandler GetMultipleHandler`, api)
   334  				assertInCode(t, `GetNotagHandler GetNotagHandler`, api)
   335  				assertInCode(t, `GetOtherReservedHandler GetOtherReservedHandler`, api)
   336  				assertInCode(t, `GetOtherUnsafeHandler GetOtherUnsafeHandler`, api)
   337  				assertInCode(t, `GetReservedHandler GetReservedHandler`, api)
   338  				assertInCode(t, `GetTestOverrideHandler GetTestOverrideHandler`, api)
   339  				assertInCode(t, `GetUnsafeHandler GetUnsafeHandler`, api)
   340  				assertInCode(t, `GetYetAnotherUnsafeHandler GetYetAnotherUnsafeHandler`, api)
   341  				assertInCode(t, `PostTestOverrideHandler PostTestOverrideHandler`, api)
   342  				assertInCode(t, `PutTestOverrideHandler PutTestOverrideHandler`, api)
   343  				assertInCode(t, `TestIDHandler TestIDHandler`, api)
   344  			},
   345  		},
   346  		"main_package": {
   347  			spec: "../fixtures/bugs/2111/fixture-2111.yaml",
   348  			prepare: func(_ *testing.T, opts *GenOpts) {
   349  				opts.IncludeMain = true
   350  				opts.MainPackage = "custom-api"
   351  				opts.SkipTagPackages = true
   352  			},
   353  			verify: func(t *testing.T, target string) {
   354  				assert.True(t, fileExists(filepath.Join(target, "cmd", "custom-api"), "main.go"))
   355  			},
   356  		},
   357  		"external_model": {
   358  			spec: "../fixtures/bugs/1897/fixture-1897.yaml",
   359  			prepare: func(t *testing.T, opts *GenOpts) {
   360  				modelOpts := *opts
   361  				modelOpts.AcceptDefinitionsOnly = true
   362  				modelOpts.Spec = "../fixtures/bugs/1897/model.yaml"
   363  				modelOpts.ModelPackage = "external"
   364  				modelOpts.Target = filepath.Dir(modelOpts.Spec)
   365  
   366  				require.NoError(t, GenerateModels(nil, &modelOpts))
   367  
   368  				t.Run("external model should be available", func(t *testing.T) {
   369  					require.True(t, fileExists(modelOpts.Target, "external"))
   370  					require.True(t, fileExists(modelOpts.Target, filepath.Join("external", "error.go")))
   371  				})
   372  
   373  				opts.IncludeMain = true
   374  			},
   375  			verify: func(t *testing.T, target string) {
   376  				location := filepath.Join(target, "cmd", "repro1897-server")
   377  				require.True(t, fileExists("", location))
   378  
   379  				t.Run("building generated server",
   380  					goExecInDir(location, "build"),
   381  				)
   382  			},
   383  			clean: func() {
   384  				// remove generated external models
   385  				_ = os.RemoveAll(filepath.Join("..", "fixtures", "bugs", "1897", "external"))
   386  			},
   387  		},
   388  		"external_models_hints": {
   389  			spec:   "../fixtures/enhancements/2224/fixture-2224.yaml",
   390  			target: "2224-hints",
   391  			prepare: func(t *testing.T, opts *GenOpts) {
   392  				modelOpts := *opts
   393  				modelOpts.AcceptDefinitionsOnly = true
   394  				modelOpts.Spec = "../fixtures/enhancements/2224/fixture-2224-models.yaml"
   395  				modelOpts.ModelPackage = "external"
   396  				modelOpts.Target = filepath.Dir(modelOpts.Spec)
   397  
   398  				require.NoError(t, GenerateModels(nil, &modelOpts))
   399  
   400  				t.Run("external models should be available", func(t *testing.T) {
   401  					require.True(t, fileExists(modelOpts.Target, "external"))
   402  
   403  					for _, model := range []string{
   404  						"access_point.go", "base.go",
   405  						"hotspot.go", "hotspot_type.go",
   406  						"incorrect.go", "json_message.go",
   407  						"json_object.go", "json_object_with_alias.go",
   408  						"object_with_embedded.go", "object_with_externals.go",
   409  						"raw.go", "request.go",
   410  						"request_pointer.go", "time_as_object.go", "time.go",
   411  					} {
   412  						require.True(t, fileExists(modelOpts.Target, filepath.Join("external", model)))
   413  					}
   414  				})
   415  
   416  				opts.IncludeMain = true
   417  			},
   418  			verify: func(t *testing.T, target string) {
   419  				// generated models (not external)
   420  				require.True(t, fileExists(target, "models"))
   421  				for _, model := range []string{"error.go", "external_with_embed.go"} {
   422  					require.True(t, fileExists(target, filepath.Join("models", model)))
   423  				}
   424  
   425  				location := filepath.Join(target, "cmd", "external-types-with-hints-server")
   426  				require.True(t, fileExists("", location))
   427  
   428  				t.Run("building generated server",
   429  					goExecInDir(location, "build"),
   430  				)
   431  			},
   432  			clean: func() {
   433  				// remove generated external models
   434  				_ = os.RemoveAll(filepath.Join("..", "fixtures", "enhancements", "2224", "external"))
   435  			},
   436  		},
   437  		"conflict_name_api_issue_2405_1": {
   438  			spec:   "../examples/todo-list/swagger.yml",
   439  			target: "2405-1",
   440  			prepare: func(_ *testing.T, opts *GenOpts) {
   441  				opts.ServerPackage = "api"
   442  				opts.IncludeMain = true
   443  			},
   444  			verify: func(t *testing.T, target string) {
   445  				location := filepath.Join(target, "cmd", "simple-to-do-list-api-server")
   446  				require.True(t, fileExists("", location))
   447  
   448  				t.Run("building generated server",
   449  					goExecInDir(location, "build"),
   450  				)
   451  			},
   452  		},
   453  		"conflict_name_api_issue_2405_2": {
   454  			spec:   "../examples/todo-list/swagger.yml",
   455  			target: "2405-2",
   456  			prepare: func(_ *testing.T, opts *GenOpts) {
   457  				opts.ServerPackage = "loads"
   458  				opts.IncludeMain = true
   459  			},
   460  			verify: func(t *testing.T, target string) {
   461  				location := filepath.Join(target, "cmd", "simple-to-do-list-api-server")
   462  				require.True(t, fileExists("", location))
   463  
   464  				t.Run("building generated server",
   465  					goExecInDir(location, "build"),
   466  				)
   467  			},
   468  		},
   469  		"conflict_name_api_issue_2405_3": {
   470  			spec:   "../fixtures/bugs/2405/fixture-2405.yaml",
   471  			target: "2405-3",
   472  			prepare: func(_ *testing.T, opts *GenOpts) {
   473  				opts.ServerPackage = "server"
   474  				opts.APIPackage = "api"
   475  				opts.IncludeMain = true
   476  			},
   477  			verify: func(t *testing.T, target string) {
   478  				location := filepath.Join(target, "cmd", "simple-to-do-list-api-server")
   479  				require.True(t, fileExists("", location))
   480  
   481  				t.Run("building generated server",
   482  					goExecInDir(location, "build"),
   483  				)
   484  			},
   485  		},
   486  		"ext_types_issue_2385": {
   487  			spec:   "../fixtures/bugs/2385/fixture-2385.yaml",
   488  			target: "2385",
   489  			prepare: func(t *testing.T, opts *GenOpts) {
   490  				opts.MainPackage = "nrcodegen-server"
   491  				opts.IncludeMain = true
   492  				location := filepath.Join(opts.Target, "models")
   493  
   494  				// add some custom model to the generated models
   495  				addModelsToLocation(t, location, "my_type.go")
   496  			},
   497  			verify: func(t *testing.T, target string) {
   498  				location := filepath.Join(target, "cmd", "nrcodegen-server")
   499  				require.True(t, fileExists("", location))
   500  
   501  				t.Run("building generated server",
   502  					goExecInDir(location, "build"),
   503  				)
   504  
   505  				location = filepath.Join(target, "models")
   506  
   507  				t.Run("building generated models",
   508  					goExecInDir(location, "build"),
   509  				)
   510  			},
   511  		},
   512  		"ext_types_full_example": {
   513  			spec:   "../examples/external-types/example-external-types.yaml",
   514  			target: "external-full",
   515  			prepare: func(t *testing.T, opts *GenOpts) {
   516  				opts.MainPackage = "nrcodegen-server"
   517  				opts.IncludeMain = true
   518  				opts.ValidateSpec = false // the spec contains AdditionalItems
   519  				location := filepath.Join(opts.Target, "models")
   520  
   521  				// add some custom model to the generated models
   522  				addModelsToLocation(t, location, "my_type.go")
   523  			},
   524  			verify: func(t *testing.T, target string) {
   525  				location := filepath.Join(target, "cmd", "nrcodegen-server")
   526  				require.True(t, fileExists("", location))
   527  
   528  				t.Run("building generated server",
   529  					goExecInDir(location, "build"),
   530  				)
   531  
   532  				location = filepath.Join(target, "models")
   533  
   534  				t.Run("building generated models",
   535  					goExecInDir(location, "build"),
   536  				)
   537  			},
   538  		},
   539  		"conflict_name_server_issue_2730": {
   540  			spec:   "../fixtures/bugs/2730/2730.yaml",
   541  			target: "server-2730",
   542  			prepare: func(_ *testing.T, opts *GenOpts) {
   543  				opts.MainPackage = "nrcodegen-server"
   544  				opts.IncludeMain = true
   545  				opts.ValidateSpec = true
   546  			},
   547  			verify: func(t *testing.T, target string) {
   548  				location := filepath.Join(target, "cmd", "nrcodegen-server")
   549  				require.True(t, fileExists("", location))
   550  
   551  				t.Run("building generated server",
   552  					goExecInDir(location, "build"),
   553  				)
   554  			},
   555  		},
   556  		"tag_package_name_issue_2866": {
   557  			spec:   "../fixtures/bugs/2866/2866.yaml",
   558  			target: "server-2866",
   559  			prepare: func(_ *testing.T, opts *GenOpts) {
   560  				opts.MainPackage = "nrcodegen-server"
   561  				opts.IncludeMain = true
   562  				opts.ValidateSpec = true
   563  			},
   564  			verify: func(t *testing.T, target string) {
   565  				location := filepath.Join(target, "cmd", "nrcodegen-server")
   566  				require.True(t, fileExists("", location))
   567  
   568  				t.Run("building generated server",
   569  					goExecInDir(location, "build"),
   570  				)
   571  			},
   572  		},
   573  	}
   574  }
   575  
   576  func generateClientFixtures(_ testing.TB) map[string]generateFixture {
   577  	return map[string]generateFixture{
   578  		"issue1083": {
   579  			spec:   "../fixtures/bugs/1083/petstore.yaml",
   580  			target: "../fixtures/bugs/1083/codegen",
   581  			prepare: func(t *testing.T, opts *GenOpts) {
   582  				input, err := os.ReadFile("../fixtures/bugs/1083/pathparam_test.go")
   583  				require.NoError(t, err)
   584  
   585  				// rewrite imports for the relocated test program
   586  				cwd := testCwd(t)
   587  				rebased := bytes.ReplaceAll(
   588  					input,
   589  					[]byte("/fixtures/bugs/1083/codegen"),
   590  					[]byte(filepath.ToSlash(strings.TrimPrefix(opts.Target, filepath.Dir(cwd)))),
   591  				)
   592  
   593  				require.NoError(t, os.WriteFile(filepath.Join(filepath.Dir(opts.Target), "pathparam_test.go"), rebased, 0o600))
   594  				opts.ExcludeSpec = false
   595  
   596  				// copy spec to run untyped server
   597  				f, err := os.Open(filepath.Join("..", "fixtures", "bugs", "1083", "petstore.yaml"))
   598  				require.NoError(t, err)
   599  				defer func() {
   600  					_ = f.Close()
   601  				}()
   602  				w, err := os.OpenFile(filepath.Join(filepath.Dir(opts.Target), "petstore.yaml"), os.O_WRONLY|os.O_TRUNC|os.O_CREATE, 0o700)
   603  				require.NoError(t, err)
   604  				defer func() {
   605  					_ = w.Close()
   606  				}()
   607  				_, err = io.Copy(w, f)
   608  				require.NoError(t, err)
   609  			},
   610  			verify: func(t *testing.T, target string) {
   611  				const packages = "./..."
   612  				testPrg := "pathparam_test.go"
   613  				testDir := filepath.Dir(target)
   614  
   615  				t.Run("go get",
   616  					goExecInDir(testDir, "get", packages),
   617  				)
   618  
   619  				t.Run("running runtime request test on generated client",
   620  					// This test runs a generated client against a untyped API server.
   621  					// It verifies that path parameters are properly escaped and unescaped.
   622  					// It exercises the full stack of runtime client and server.
   623  					goExecInDir(testDir, "test", "-v", testPrg),
   624  				)
   625  			},
   626  		},
   627  		"conflict_name_client_issue_2730": {
   628  			spec:    "../fixtures/bugs/2730/2730.yaml",
   629  			target:  "server-2730",
   630  			prepare: func(_ *testing.T, _ *GenOpts) {},
   631  			verify: func(t *testing.T, target string) {
   632  				location := filepath.Join(target, "client")
   633  				require.True(t, fileExists("", location))
   634  
   635  				t.Run("building generated client",
   636  					goExecInDir(location, "build"),
   637  				)
   638  			},
   639  		},
   640  	}
   641  }
   642  
   643  func addModelsToLocation(t testing.TB, location, file string) {
   644  	// writes some external model to a file to supplement codegen
   645  	// (test external types)
   646  	require.NoError(t, os.MkdirAll(location, 0o700))
   647  
   648  	require.NoError(t, os.WriteFile(filepath.Join(location, file), []byte(`
   649  package models
   650  
   651  import (
   652    "context"
   653    "io"
   654    "github.com/go-openapi/strfmt"
   655  )
   656  
   657  // MyType ...
   658  type MyType string
   659  
   660  // Validate MyType
   661  func (MyType) Validate(strfmt.Registry) error { return nil }
   662  func (MyType) ContextValidate(context.Context, strfmt.Registry) error { return nil }
   663  
   664  // MyInteger ...
   665  type MyInteger int
   666  
   667  // Validate MyInteger
   668  func (MyInteger) Validate(strfmt.Registry) error { return nil }
   669  func (MyInteger) ContextValidate(context.Context, strfmt.Registry) error { return nil }
   670  
   671  // MyString ...
   672  type MyString string
   673  
   674  // Validate MyString
   675  func (MyString) Validate(strfmt.Registry) error { return nil }
   676  func (MyString) ContextValidate(context.Context, strfmt.Registry) error { return nil }
   677  
   678  // MyOtherType ...
   679  type MyOtherType struct{}
   680  
   681  // Validate MyOtherType
   682  func (MyOtherType) Validate(strfmt.Registry) error { return nil }
   683  func (MyOtherType) ContextValidate(context.Context, strfmt.Registry) error { return nil }
   684  
   685  // MyStreamer ...
   686  type MyStreamer io.Reader
   687  `),
   688  		os.ModePerm))
   689  }