github.com/emreu/go-swagger@v0.22.1/generator/operation_test.go (about)

     1  // Copyright 2015 go-swagger maintainers
     2  //
     3  // Licensed under the Apache License, Version 2.0 (the "License");
     4  // you may not use this file except in compliance with the License.
     5  // You may obtain a copy of the License at
     6  //
     7  //    http://www.apache.org/licenses/LICENSE-2.0
     8  //
     9  // Unless required by applicable law or agreed to in writing, software
    10  // distributed under the License is distributed on an "AS IS" BASIS,
    11  // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    12  // See the License for the specific language governing permissions and
    13  // limitations under the License.
    14  
    15  package generator
    16  
    17  import (
    18  	"bytes"
    19  	"errors"
    20  	"fmt"
    21  	"io/ioutil"
    22  	"log"
    23  	"os"
    24  	"path/filepath"
    25  	"testing"
    26  
    27  	"github.com/go-openapi/analysis"
    28  	"github.com/go-openapi/loads"
    29  	"github.com/go-openapi/spec"
    30  	"github.com/stretchr/testify/assert"
    31  )
    32  
    33  func TestUniqueOperationNames(t *testing.T) {
    34  	doc, err := loads.Spec("../fixtures/codegen/todolist.simple.yml")
    35  	if assert.NoError(t, err) {
    36  		sp := doc.Spec()
    37  		sp.Paths.Paths["/tasks"].Post.ID = "saveTask"
    38  		sp.Paths.Paths["/tasks"].Post.AddExtension("origName", "createTask")
    39  		sp.Paths.Paths["/tasks/{id}"].Put.ID = "saveTask"
    40  		sp.Paths.Paths["/tasks/{id}"].Put.AddExtension("origName", "updateTask")
    41  		analyzed := analysis.New(sp)
    42  
    43  		ops := gatherOperations(analyzed, nil)
    44  		assert.Len(t, ops, 6)
    45  		_, exists := ops["saveTask"]
    46  		assert.True(t, exists)
    47  		_, exists = ops["PutTasksID"]
    48  		assert.True(t, exists)
    49  	}
    50  }
    51  
    52  func TestEmptyOperationNames(t *testing.T) {
    53  	doc, err := loads.Spec("../fixtures/codegen/todolist.simple.yml")
    54  	if assert.NoError(t, err) {
    55  		sp := doc.Spec()
    56  		sp.Paths.Paths["/tasks"].Post.ID = ""
    57  		sp.Paths.Paths["/tasks"].Post.AddExtension("origName", "createTask")
    58  		sp.Paths.Paths["/tasks/{id}"].Put.ID = ""
    59  		sp.Paths.Paths["/tasks/{id}"].Put.AddExtension("origName", "updateTask")
    60  		analyzed := analysis.New(sp)
    61  
    62  		ops := gatherOperations(analyzed, nil)
    63  		assert.Len(t, ops, 6)
    64  		_, exists := ops["PostTasks"]
    65  		assert.True(t, exists)
    66  		_, exists = ops["PutTasksID"]
    67  		assert.True(t, exists)
    68  	}
    69  }
    70  
    71  func TestMakeResponseHeader(t *testing.T) {
    72  	b, err := opBuilder("getTasks", "")
    73  	if assert.NoError(t, err) {
    74  		hdr := findResponseHeader(&b.Operation, 200, "X-Rate-Limit")
    75  		gh, er := b.MakeHeader("a", "X-Rate-Limit", *hdr)
    76  		if assert.NoError(t, er) {
    77  			assert.True(t, gh.IsPrimitive)
    78  			assert.Equal(t, "int32", gh.GoType)
    79  			assert.Equal(t, "X-Rate-Limit", gh.Name)
    80  		}
    81  	}
    82  }
    83  
    84  func TestMakeResponseHeaderDefaultValues(t *testing.T) {
    85  	b, err := opBuilder("getTasks", "")
    86  	if assert.NoError(t, err) {
    87  		var testCases = []struct {
    88  			name         string      // input
    89  			typeStr      string      // expected type
    90  			defaultValue interface{} // expected result
    91  		}{
    92  			{"Access-Control-Allow-Origin", "string", "*"},
    93  			{"X-Rate-Limit", "int32", nil},
    94  			{"X-Rate-Limit-Remaining", "int32", float64(42)},
    95  			{"X-Rate-Limit-Reset", "int32", "1449875311"},
    96  			{"X-Rate-Limit-Reset-Human", "string", "3 days"},
    97  			{"X-Rate-Limit-Reset-Human-Number", "string", float64(3)},
    98  		}
    99  
   100  		for _, tc := range testCases {
   101  			// t.Logf("tc: %+v", tc)
   102  			hdr := findResponseHeader(&b.Operation, 200, tc.name)
   103  			assert.NotNil(t, hdr)
   104  			gh, er := b.MakeHeader("a", tc.name, *hdr)
   105  			if assert.NoError(t, er) {
   106  				assert.True(t, gh.IsPrimitive)
   107  				assert.Equal(t, tc.typeStr, gh.GoType)
   108  				assert.Equal(t, tc.name, gh.Name)
   109  				assert.Exactly(t, tc.defaultValue, gh.Default)
   110  			}
   111  		}
   112  	}
   113  }
   114  
   115  func TestMakeResponse(t *testing.T) {
   116  	b, err := opBuilder("getTasks", "")
   117  	if assert.NoError(t, err) {
   118  		resolver := &typeResolver{ModelsPackage: b.ModelsPackage, Doc: b.Doc}
   119  		resolver.KnownDefs = make(map[string]struct{})
   120  		for k := range b.Doc.Spec().Definitions {
   121  			resolver.KnownDefs[k] = struct{}{}
   122  		}
   123  		gO, err := b.MakeResponse("a", "getTasksSuccess", true, resolver, 200, b.Operation.Responses.StatusCodeResponses[200])
   124  		if assert.NoError(t, err) {
   125  			assert.Len(t, gO.Headers, 6)
   126  			assert.NotNil(t, gO.Schema)
   127  			assert.True(t, gO.Schema.IsArray)
   128  			assert.NotNil(t, gO.Schema.Items)
   129  			assert.False(t, gO.Schema.IsAnonymous)
   130  			assert.Equal(t, "[]*models.Task", gO.Schema.GoType)
   131  		}
   132  	}
   133  }
   134  
   135  func TestMakeResponse_WithAllOfSchema(t *testing.T) {
   136  	b, err := methodPathOpBuilder("get", "/media/search", "../fixtures/codegen/instagram.yml")
   137  	if assert.NoError(t, err) {
   138  		resolver := &typeResolver{ModelsPackage: b.ModelsPackage, Doc: b.Doc}
   139  		resolver.KnownDefs = make(map[string]struct{})
   140  		for k := range b.Doc.Spec().Definitions {
   141  			resolver.KnownDefs[k] = struct{}{}
   142  		}
   143  		gO, err := b.MakeResponse("a", "get /media/search", true, resolver, 200, b.Operation.Responses.StatusCodeResponses[200])
   144  		if assert.NoError(t, err) {
   145  			if assert.NotNil(t, gO.Schema) {
   146  				assert.Equal(t, "GetMediaSearchBody", gO.Schema.GoType)
   147  			}
   148  			if assert.NotEmpty(t, b.ExtraSchemas) {
   149  				body := b.ExtraSchemas["GetMediaSearchBody"]
   150  				if assert.NotEmpty(t, body.Properties) {
   151  					prop := body.Properties[0]
   152  					assert.Equal(t, "data", prop.Name)
   153  					// is in models only when definition is flattened: otherwise, ExtraSchema is rendered in operations package
   154  					assert.Equal(t, "[]*DataItems0", prop.GoType)
   155  				}
   156  				items := b.ExtraSchemas["DataItems0"]
   157  				if assert.NotEmpty(t, items.AllOf) {
   158  					media := items.AllOf[0]
   159  					// expect #definitions/media to be captured and reused by ExtraSchema
   160  					assert.Equal(t, "models.Media", media.GoType)
   161  				}
   162  			}
   163  		}
   164  	}
   165  }
   166  
   167  func TestMakeOperationParam(t *testing.T) {
   168  	b, err := opBuilder("getTasks", "")
   169  	if assert.NoError(t, err) {
   170  		resolver := &typeResolver{ModelsPackage: b.ModelsPackage, Doc: b.Doc}
   171  		gO, err := b.MakeParameter("a", resolver, b.Operation.Parameters[0], nil)
   172  		if assert.NoError(t, err) {
   173  			assert.Equal(t, "size", gO.Name)
   174  			assert.True(t, gO.IsPrimitive)
   175  		}
   176  	}
   177  }
   178  
   179  func TestMakeOperationParamItem(t *testing.T) {
   180  	b, err := opBuilder("arrayQueryParams", "../fixtures/codegen/todolist.arrayquery.yml")
   181  	if assert.NoError(t, err) {
   182  		resolver := &typeResolver{ModelsPackage: b.ModelsPackage, Doc: b.Doc}
   183  		gO, err := b.MakeParameterItem("a", "siString", "ii", "siString", "a.SiString", "query", resolver, b.Operation.Parameters[1].Items, nil)
   184  		if assert.NoError(t, err) {
   185  			assert.Nil(t, gO.Parent)
   186  			assert.True(t, gO.IsPrimitive)
   187  		}
   188  	}
   189  }
   190  
   191  func TestMakeOperation(t *testing.T) {
   192  	b, err := opBuilder("getTasks", "")
   193  	if assert.NoError(t, err) {
   194  		gO, err := b.MakeOperation()
   195  		if assert.NoError(t, err) {
   196  			assert.Equal(t, "getTasks", gO.Name)
   197  			assert.Equal(t, "GET", gO.Method)
   198  			assert.Equal(t, "/tasks", gO.Path)
   199  			assert.Len(t, gO.Params, 2)
   200  			assert.Len(t, gO.Responses, 1)
   201  			assert.NotNil(t, gO.DefaultResponse)
   202  			assert.NotNil(t, gO.SuccessResponse)
   203  		}
   204  	}
   205  }
   206  
   207  func TestRenderOperation_InstagramSearch(t *testing.T) {
   208  	log.SetOutput(ioutil.Discard)
   209  	defer log.SetOutput(os.Stdout)
   210  
   211  	b, err := methodPathOpBuilder("get", "/media/search", "../fixtures/codegen/instagram.yml")
   212  	if assert.NoError(t, err) {
   213  		gO, ero := b.MakeOperation()
   214  		if assert.NoError(t, ero) {
   215  			buf := bytes.NewBuffer(nil)
   216  			opts := opts()
   217  			ert := templates.MustGet("serverOperation").Execute(buf, gO)
   218  			if assert.NoError(t, ert) {
   219  				ff, erf := opts.LanguageOpts.FormatContent("operation.go", buf.Bytes())
   220  				if assert.NoError(t, erf) {
   221  					res := string(ff)
   222  					assertInCode(t, "type GetMediaSearchOKBody struct {", res)
   223  					// codegen does not assumes objects are only in models
   224  					// this is inlined
   225  					assertInCode(t, "Data []*DataItems0 `json:\"data\"`", res)
   226  					assertInCode(t, "type DataItems0 struct {", res)
   227  					// this is a definition: expect this definition to be reused from the models pkg
   228  					assertInCode(t, "models.Media", res)
   229  				} else {
   230  					fmt.Println(buf.String())
   231  					t.FailNow()
   232  				}
   233  			} else {
   234  				t.FailNow()
   235  			}
   236  
   237  			buf = bytes.NewBuffer(nil)
   238  			ert = templates.MustGet("serverResponses").Execute(buf, gO)
   239  			if assert.NoError(t, ert) {
   240  				ff, erf := opts.LanguageOpts.FormatContent("response.go", buf.Bytes())
   241  				if assert.NoError(t, erf) {
   242  					res := string(ff)
   243  					// codegen does not assumes objects are only in models
   244  					assertInCode(t, "type GetMediaSearchOK struct {", res)
   245  					assertInCode(t, "GetMediaSearchOKBody", res)
   246  				} else {
   247  					fmt.Println(buf.String())
   248  					t.FailNow()
   249  				}
   250  			} else {
   251  				t.FailNow()
   252  			}
   253  		}
   254  	}
   255  	b, err = methodPathOpBuilderWithFlatten("get", "/media/search", "../fixtures/codegen/instagram.yml")
   256  	if assert.NoError(t, err) {
   257  		gO, ero := b.MakeOperation()
   258  		if assert.NoError(t, ero) {
   259  			buf := bytes.NewBuffer(nil)
   260  			opts := opts()
   261  			ert := templates.MustGet("serverOperation").Execute(buf, gO)
   262  			if assert.NoError(t, ert) {
   263  				ff, erf := opts.LanguageOpts.FormatContent("operation.go", buf.Bytes())
   264  				if assert.NoError(t, erf) {
   265  					res := string(ff)
   266  					assertNotInCode(t, "DataItems0", res)
   267  					assertNotInCode(t, "models", res)
   268  				} else {
   269  					fmt.Println(buf.String())
   270  					t.FailNow()
   271  				}
   272  			} else {
   273  				t.FailNow()
   274  			}
   275  			buf = bytes.NewBuffer(nil)
   276  			ert = templates.MustGet("serverResponses").Execute(buf, gO)
   277  			if assert.NoError(t, ert) {
   278  				ff, erf := opts.LanguageOpts.FormatContent("operation.go", buf.Bytes())
   279  				if assert.NoError(t, erf) {
   280  					res := string(ff)
   281  					assertInCode(t, "Payload *models.GetMediaSearchOKBody", res)
   282  				} else {
   283  					fmt.Println(buf.String())
   284  				}
   285  			}
   286  		}
   287  	}
   288  }
   289  
   290  func methodPathOpBuilder(method, path, fname string) (codeGenOpBuilder, error) {
   291  	if fname == "" {
   292  		fname = "../fixtures/codegen/todolist.simple.yml"
   293  	}
   294  
   295  	specDoc, err := loads.Spec(fname)
   296  	if err != nil {
   297  		return codeGenOpBuilder{}, err
   298  	}
   299  
   300  	analyzed := analysis.New(specDoc.Spec())
   301  	op, ok := analyzed.OperationFor(method, path)
   302  	if !ok {
   303  		return codeGenOpBuilder{}, errors.New("No operation could be found for " + method + " " + path)
   304  	}
   305  
   306  	return codeGenOpBuilder{
   307  		Name:          method + " " + path,
   308  		Method:        method,
   309  		Path:          path,
   310  		APIPackage:    "restapi",
   311  		ModelsPackage: "models",
   312  		Principal:     "models.User",
   313  		Target:        ".",
   314  		Operation:     *op,
   315  		Doc:           specDoc,
   316  		Analyzed:      analyzed,
   317  		Authed:        false,
   318  		ExtraSchemas:  make(map[string]GenSchema),
   319  		GenOpts:       opts(),
   320  	}, nil
   321  }
   322  
   323  // methodPathOpBuilderWithFlatten prepares an operation build based on method and path, with spec full flattening
   324  func methodPathOpBuilderWithFlatten(method, path, fname string) (codeGenOpBuilder, error) {
   325  	if fname == "" {
   326  		fname = "../fixtures/codegen/todolist.simple.yml"
   327  	}
   328  
   329  	specDoc, err := loads.Spec(fname)
   330  	if err != nil {
   331  		return codeGenOpBuilder{}, err
   332  	}
   333  
   334  	o := opBuildGetOpts(fname, true, false) // flatten: true, minimal: false
   335  
   336  	specDoc, err = validateAndFlattenSpec(o, specDoc)
   337  	if err != nil {
   338  		return codeGenOpBuilder{}, err
   339  	}
   340  
   341  	analyzed := analysis.New(specDoc.Spec())
   342  	op, ok := analyzed.OperationFor(method, path)
   343  	if !ok {
   344  		return codeGenOpBuilder{}, errors.New("No operation could be found for " + method + " " + path)
   345  	}
   346  
   347  	return codeGenOpBuilder{
   348  		Name:          method + " " + path,
   349  		Method:        method,
   350  		Path:          path,
   351  		APIPackage:    "restapi",
   352  		ModelsPackage: "models",
   353  		Principal:     "models.User",
   354  		Target:        ".",
   355  		Operation:     *op,
   356  		Doc:           specDoc,
   357  		Analyzed:      analyzed,
   358  		Authed:        false,
   359  		ExtraSchemas:  make(map[string]GenSchema),
   360  		GenOpts:       opts(),
   361  	}, nil
   362  }
   363  
   364  // opBuilderWithOpts prepares the making of an operation with spec flattening options
   365  func opBuilderWithOpts(name, fname string, o *GenOpts) (codeGenOpBuilder, error) {
   366  	if fname == "" {
   367  		// default fixture
   368  		fname = "../fixtures/codegen/todolist.simple.yml"
   369  	}
   370  
   371  	if !filepath.IsAbs(fname) {
   372  		cwd, _ := os.Getwd()
   373  		fname = filepath.Join(cwd, fname)
   374  	}
   375  
   376  	specDoc, err := loads.Spec(fname)
   377  	if err != nil {
   378  		return codeGenOpBuilder{}, err
   379  	}
   380  	o.Spec = fname
   381  
   382  	log.SetOutput(ioutil.Discard)
   383  	defer log.SetOutput(os.Stdout)
   384  	specDoc, err = validateAndFlattenSpec(o, specDoc)
   385  	if err != nil {
   386  		return codeGenOpBuilder{}, err
   387  	}
   388  	log.SetOutput(os.Stdout)
   389  
   390  	analyzed := analysis.New(specDoc.Spec())
   391  
   392  	method, path, op, ok := analyzed.OperationForName(name)
   393  	if !ok {
   394  		return codeGenOpBuilder{}, errors.New("No operation could be found for " + name)
   395  	}
   396  
   397  	return codeGenOpBuilder{
   398  		Name:          name,
   399  		Method:        method,
   400  		Path:          path,
   401  		BasePath:      specDoc.BasePath(),
   402  		APIPackage:    "restapi",
   403  		ModelsPackage: "models",
   404  		Principal:     "models.User",
   405  		Target:        ".",
   406  		Operation:     *op,
   407  		Doc:           specDoc,
   408  		Analyzed:      analyzed,
   409  		Authed:        false,
   410  		ExtraSchemas:  make(map[string]GenSchema),
   411  		GenOpts:       o, // opts()??
   412  	}, nil
   413  }
   414  
   415  func opBuildGetOpts(specName string, withFlatten bool, withMinimalFlatten bool) (opts *GenOpts) {
   416  	opts = &GenOpts{}
   417  	if erd := opts.EnsureDefaults(); erd != nil {
   418  		panic("Cannot initialize GenOpts")
   419  	}
   420  	opts.ValidateSpec = true
   421  	opts.FlattenOpts.Expand = !withFlatten
   422  	opts.FlattenOpts.Minimal = withMinimalFlatten
   423  	opts.Spec = specName
   424  	return
   425  }
   426  
   427  // opBuilderWithFlatten prepares the making of an operation with spec full flattening prior to rendering
   428  func opBuilderWithFlatten(name, fname string) (codeGenOpBuilder, error) {
   429  	o := opBuildGetOpts(fname, true, false) // flatten: true, minimal: false
   430  	return opBuilderWithOpts(name, fname, o)
   431  }
   432  
   433  // opBuilderWithExpand prepares the making of an operation with spec expansion prior to rendering
   434  func opBuilderWithExpand(name, fname string) (codeGenOpBuilder, error) {
   435  	o := opBuildGetOpts(fname, false, false) // flatten: false => expand
   436  	return opBuilderWithOpts(name, fname, o)
   437  }
   438  
   439  // opBuilder prepares the making of an operation with spec minimal flattening (default for CLI)
   440  func opBuilder(name, fname string) (codeGenOpBuilder, error) {
   441  	o := opBuildGetOpts(fname, true, true) // flatten:true, minimal: true
   442  	// some fixtures do not fully validate - skip this
   443  	o.ValidateSpec = false
   444  	return opBuilderWithOpts(name, fname, o)
   445  }
   446  
   447  func findResponseHeader(op *spec.Operation, code int, name string) *spec.Header {
   448  	resp := op.Responses.Default
   449  	if code > 0 {
   450  		bb, ok := op.Responses.StatusCodeResponses[code]
   451  		if ok {
   452  			resp = &bb
   453  		}
   454  	}
   455  
   456  	if resp == nil {
   457  		return nil
   458  	}
   459  
   460  	hdr, ok := resp.Headers[name]
   461  	if !ok {
   462  		return nil
   463  	}
   464  
   465  	return &hdr
   466  }
   467  
   468  func TestDateFormat_Spec1(t *testing.T) {
   469  	b, err := opBuilder("putTesting", "../fixtures/bugs/193/spec1.json")
   470  	if assert.NoError(t, err) {
   471  		op, err := b.MakeOperation()
   472  		if assert.NoError(t, err) {
   473  			buf := bytes.NewBuffer(nil)
   474  			opts := opts()
   475  			opts.defaultsEnsured = false
   476  			opts.IsClient = true
   477  			err = opts.EnsureDefaults()
   478  			assert.NoError(t, err)
   479  			err = templates.MustGet("clientParameter").Execute(buf, op)
   480  			if assert.NoError(t, err) {
   481  				ff, err := opts.LanguageOpts.FormatContent("put_testing.go", buf.Bytes())
   482  				if assert.NoError(t, err) {
   483  					res := string(ff)
   484  					assertInCode(t, "frTestingThis.String()", res)
   485  				} else {
   486  					fmt.Println(buf.String())
   487  				}
   488  			}
   489  		}
   490  	}
   491  }
   492  
   493  func TestDateFormat_Spec2(t *testing.T) {
   494  	b, err := opBuilder("putTesting", "../fixtures/bugs/193/spec2.json")
   495  	if assert.NoError(t, err) {
   496  		op, err := b.MakeOperation()
   497  		if assert.NoError(t, err) {
   498  			buf := bytes.NewBuffer(nil)
   499  			opts := opts()
   500  			opts.defaultsEnsured = false
   501  			opts.IsClient = true
   502  			err = opts.EnsureDefaults()
   503  			assert.NoError(t, err)
   504  			err = templates.MustGet("clientParameter").Execute(buf, op)
   505  			if assert.NoError(t, err) {
   506  				ff, err := opts.LanguageOpts.FormatContent("put_testing.go", buf.Bytes())
   507  				if assert.NoError(t, err) {
   508  					res := string(ff)
   509  					assertInCode(t, "valuesTestingThis = append(valuesTestingThis, v.String())", res)
   510  				} else {
   511  					fmt.Println(buf.String())
   512  				}
   513  			}
   514  		}
   515  	}
   516  }
   517  
   518  func TestBuilder_Issue1703(t *testing.T) {
   519  	log.SetOutput(ioutil.Discard)
   520  	defer log.SetOutput(os.Stdout)
   521  	dr, err := os.Getwd()
   522  	assert.NoError(t, err)
   523  
   524  	opts := &GenOpts{
   525  		Spec:              filepath.FromSlash("../fixtures/codegen/existing-model.yml"),
   526  		IncludeModel:      true,
   527  		IncludeValidator:  true,
   528  		IncludeHandler:    true,
   529  		IncludeParameters: true,
   530  		IncludeResponses:  true,
   531  		IncludeMain:       true,
   532  		APIPackage:        "restapi",
   533  		ModelPackage:      "model",
   534  		ServerPackage:     "server",
   535  		ClientPackage:     "client",
   536  		Target:            dr,
   537  	}
   538  	err = opts.EnsureDefaults()
   539  	assert.NoError(t, err)
   540  	appGen, err := newAppGenerator("x-go-type-import-bug", nil, nil, opts)
   541  	if assert.NoError(t, err) {
   542  		op, err := appGen.makeCodegenApp()
   543  		if assert.NoError(t, err) {
   544  			for _, o := range op.Operations {
   545  				buf := bytes.NewBuffer(nil)
   546  				err := templates.MustGet("serverResponses").Execute(buf, o)
   547  				if assert.NoError(t, err) {
   548  					ff, err := appGen.GenOpts.LanguageOpts.FormatContent("response.go", buf.Bytes())
   549  					if assert.NoError(t, err) {
   550  						res := string(ff)
   551  						assertInCode(t, "jwk \"github.com/user/package\"", res)
   552  					} else {
   553  						fmt.Println(buf.String())
   554  					}
   555  				}
   556  			}
   557  		}
   558  	}
   559  }
   560  
   561  func TestBuilder_Issue287(t *testing.T) {
   562  	log.SetOutput(ioutil.Discard)
   563  	defer log.SetOutput(os.Stdout)
   564  	dr, _ := os.Getwd()
   565  
   566  	opts := &GenOpts{
   567  		Spec:              filepath.FromSlash("../fixtures/bugs/287/swagger.yml"),
   568  		IncludeModel:      true,
   569  		IncludeValidator:  true,
   570  		IncludeHandler:    true,
   571  		IncludeParameters: true,
   572  		IncludeResponses:  true,
   573  		IncludeMain:       true,
   574  		APIPackage:        "restapi",
   575  		ModelPackage:      "model",
   576  		ServerPackage:     "server",
   577  		ClientPackage:     "client",
   578  		Target:            dr,
   579  	}
   580  	err := opts.EnsureDefaults()
   581  	assert.NoError(t, err)
   582  	appGen, err := newAppGenerator("plainTexter", nil, nil, opts)
   583  	if assert.NoError(t, err) {
   584  		op, err := appGen.makeCodegenApp()
   585  		if assert.NoError(t, err) {
   586  			buf := bytes.NewBuffer(nil)
   587  			err := templates.MustGet("serverBuilder").Execute(buf, op)
   588  			if assert.NoError(t, err) {
   589  				ff, err := appGen.GenOpts.LanguageOpts.FormatContent("put_testing.go", buf.Bytes())
   590  				if assert.NoError(t, err) {
   591  					res := string(ff)
   592  					assertInCode(t, "case \"text/plain\":", res)
   593  				} else {
   594  					fmt.Println(buf.String())
   595  				}
   596  			}
   597  		}
   598  	}
   599  }
   600  
   601  func TestBuilder_Issue465(t *testing.T) {
   602  	log.SetOutput(ioutil.Discard)
   603  	defer log.SetOutput(os.Stdout)
   604  	dr, _ := os.Getwd()
   605  	opts := &GenOpts{
   606  		Spec:              filepath.FromSlash("../fixtures/bugs/465/swagger.yml"),
   607  		IncludeModel:      true,
   608  		IncludeValidator:  true,
   609  		IncludeHandler:    true,
   610  		IncludeParameters: true,
   611  		IncludeResponses:  true,
   612  		IncludeMain:       true,
   613  		APIPackage:        "restapi",
   614  		ModelPackage:      "model",
   615  		ServerPackage:     "server",
   616  		ClientPackage:     "client",
   617  		Target:            dr,
   618  		IsClient:          true,
   619  	}
   620  	err := opts.EnsureDefaults()
   621  	assert.NoError(t, err)
   622  	appGen, err := newAppGenerator("plainTexter", nil, nil, opts)
   623  
   624  	if assert.NoError(t, err) {
   625  		op, err := appGen.makeCodegenApp()
   626  		if assert.NoError(t, err) {
   627  			buf := bytes.NewBuffer(nil)
   628  			err := templates.MustGet("clientFacade").Execute(buf, op)
   629  			if assert.NoError(t, err) {
   630  				ff, err := appGen.GenOpts.LanguageOpts.FormatContent("put_testing.go", buf.Bytes())
   631  				if assert.NoError(t, err) {
   632  					res := string(ff)
   633  					assertInCode(t, "/v1/fancyAPI", res)
   634  				} else {
   635  					fmt.Println(buf.String())
   636  				}
   637  			}
   638  		}
   639  	}
   640  }
   641  
   642  func TestBuilder_Issue500(t *testing.T) {
   643  	log.SetOutput(ioutil.Discard)
   644  	defer log.SetOutput(os.Stdout)
   645  	dr, _ := os.Getwd()
   646  	opts := &GenOpts{
   647  		Spec:              filepath.FromSlash("../fixtures/bugs/500/swagger.yml"),
   648  		IncludeModel:      true,
   649  		IncludeValidator:  true,
   650  		IncludeHandler:    true,
   651  		IncludeParameters: true,
   652  		IncludeResponses:  true,
   653  		IncludeMain:       true,
   654  		APIPackage:        "restapi",
   655  		ModelPackage:      "model",
   656  		ServerPackage:     "server",
   657  		ClientPackage:     "client",
   658  		Target:            dr,
   659  	}
   660  	err := opts.EnsureDefaults()
   661  	assert.NoError(t, err)
   662  	appGen, err := newAppGenerator("multiTags", nil, nil, opts)
   663  	if assert.NoError(t, err) {
   664  		op, err := appGen.makeCodegenApp()
   665  		if assert.NoError(t, err) {
   666  			buf := bytes.NewBuffer(nil)
   667  			err := templates.MustGet("serverBuilder").Execute(buf, op)
   668  			if assert.NoError(t, err) {
   669  				ff, err := appGen.GenOpts.LanguageOpts.FormatContent("put_testing.go", buf.Bytes())
   670  				if assert.NoError(t, err) {
   671  					res := string(ff)
   672  					assertNotInCode(t, `o.handlers["GET"]["/payment/{invoice_id}/payments/{payment_id}"] = NewGetPaymentByID(o.context, o.GetPaymentByIDHandler)`, res)
   673  					assertInCode(t, `o.handlers["GET"]["/payment/{invoice_id}/payments/{payment_id}"] = invoices.NewGetPaymentByID(o.context, o.InvoicesGetPaymentByIDHandler)`, res)
   674  				} else {
   675  					fmt.Println(buf.String())
   676  				}
   677  			}
   678  		}
   679  	}
   680  }
   681  
   682  func TestGenClient_IllegalBOM(t *testing.T) {
   683  	b, err := methodPathOpBuilder("get", "/v3/attachments/{attachmentId}", "../fixtures/bugs/727/swagger.json")
   684  	if assert.NoError(t, err) {
   685  		op, err := b.MakeOperation()
   686  		if assert.NoError(t, err) {
   687  			buf := bytes.NewBuffer(nil)
   688  			opts := opts()
   689  			opts.defaultsEnsured = false
   690  			opts.IsClient = true
   691  			err = opts.EnsureDefaults()
   692  			assert.NoError(t, err)
   693  			err = templates.MustGet("clientResponse").Execute(buf, op)
   694  			assert.NoError(t, err)
   695  		}
   696  	}
   697  }
   698  
   699  func TestGenClient_CustomFormatPath(t *testing.T) {
   700  	b, err := methodPathOpBuilder("get", "/mosaic/experimental/series/{SeriesId}/mosaics", "../fixtures/bugs/789/swagger.yml")
   701  	if assert.NoError(t, err) {
   702  		op, err := b.MakeOperation()
   703  		if assert.NoError(t, err) {
   704  			buf := bytes.NewBuffer(nil)
   705  			opts := opts()
   706  			opts.defaultsEnsured = false
   707  			opts.IsClient = true
   708  			err = opts.EnsureDefaults()
   709  			assert.NoError(t, err)
   710  			err = templates.MustGet("clientParameter").Execute(buf, op)
   711  			if assert.NoError(t, err) {
   712  				assertInCode(t, `if err := r.SetPathParam("SeriesId", o.SeriesID.String()); err != nil`, buf.String())
   713  			}
   714  		}
   715  	}
   716  }
   717  
   718  func TestGenClient_Issue733(t *testing.T) {
   719  	b, err := opBuilder("get_characters_character_id_mail_mail_id", "../fixtures/bugs/733/swagger.json")
   720  	if assert.NoError(t, err) {
   721  		op, err := b.MakeOperation()
   722  		if assert.NoError(t, err) {
   723  			buf := bytes.NewBuffer(nil)
   724  			opts := opts()
   725  			opts.defaultsEnsured = false
   726  			opts.IsClient = true
   727  			err = opts.EnsureDefaults()
   728  			assert.NoError(t, err)
   729  			err = templates.MustGet("clientResponse").Execute(buf, op)
   730  			if assert.NoError(t, err) {
   731  				assertInCode(t, "Labels []*int64 `json:\"labels\"`", buf.String())
   732  			}
   733  		}
   734  	}
   735  }
   736  
   737  func TestGenServerIssue890_ValidationTrueFlatteningTrue(t *testing.T) {
   738  	log.SetOutput(ioutil.Discard)
   739  	defer log.SetOutput(os.Stdout)
   740  	dr, _ := os.Getwd()
   741  	opts := &GenOpts{
   742  		Spec:              filepath.FromSlash("../fixtures/bugs/890/swagger.yaml"),
   743  		IncludeModel:      true,
   744  		IncludeValidator:  true,
   745  		IncludeHandler:    true,
   746  		IncludeParameters: true,
   747  		IncludeResponses:  true,
   748  		IncludeMain:       true,
   749  		ValidateSpec:      true,
   750  		APIPackage:        "restapi",
   751  		ModelPackage:      "model",
   752  		ServerPackage:     "server",
   753  		ClientPackage:     "client",
   754  		Target:            dr,
   755  		IsClient:          true,
   756  	}
   757  
   758  	//Testing Server Generation
   759  	err := opts.EnsureDefaults()
   760  	// Full flattening
   761  	opts.FlattenOpts.Expand = false
   762  	opts.FlattenOpts.Minimal = false
   763  	assert.NoError(t, err)
   764  	appGen, err := newAppGenerator("JsonRefOperation", nil, nil, opts)
   765  	if assert.NoError(t, err) {
   766  		op, err := appGen.makeCodegenApp()
   767  		if assert.NoError(t, err) {
   768  			buf := bytes.NewBuffer(nil)
   769  			err := templates.MustGet("serverOperation").Execute(buf, op.Operations[0])
   770  			if assert.NoError(t, err) {
   771  				filecontent, err := appGen.GenOpts.LanguageOpts.FormatContent("operation.go", buf.Bytes())
   772  				if assert.NoError(t, err) {
   773  					res := string(filecontent)
   774  					assertInCode(t, "GetHealthCheck", res)
   775  				} else {
   776  					fmt.Println(buf.String())
   777  				}
   778  			}
   779  		}
   780  	}
   781  }
   782  
   783  func TestGenClientIssue890_ValidationTrueFlatteningTrue(t *testing.T) {
   784  	log.SetOutput(ioutil.Discard)
   785  	defer func() {
   786  		log.SetOutput(os.Stdout)
   787  		dr, _ := os.Getwd()
   788  		_ = os.RemoveAll(filepath.Join(filepath.FromSlash(dr), "restapi"))
   789  	}()
   790  	opts := testGenOpts()
   791  	opts.Spec = "../fixtures/bugs/890/swagger.yaml"
   792  	opts.ValidateSpec = true
   793  	opts.FlattenOpts.Minimal = false
   794  	// Testing this is enough as there is only one operation which is specified as $ref.
   795  	// If this doesn't get resolved then there will be an error definitely.
   796  	assert.NoError(t, GenerateClient("foo", nil, nil, &opts))
   797  }
   798  
   799  func TestGenServerIssue890_ValidationFalseFlattenTrue(t *testing.T) {
   800  	log.SetOutput(ioutil.Discard)
   801  	defer log.SetOutput(os.Stdout)
   802  	dr, _ := os.Getwd()
   803  	opts := &GenOpts{
   804  		Spec:              filepath.FromSlash("../fixtures/bugs/890/swagger.yaml"),
   805  		IncludeModel:      true,
   806  		IncludeValidator:  true,
   807  		IncludeHandler:    true,
   808  		IncludeParameters: true,
   809  		IncludeResponses:  true,
   810  		IncludeMain:       true,
   811  		APIPackage:        "restapi",
   812  		ModelPackage:      "model",
   813  		ServerPackage:     "server",
   814  		ClientPackage:     "client",
   815  		Target:            dr,
   816  		IsClient:          true,
   817  	}
   818  
   819  	//Testing Server Generation
   820  	err := opts.EnsureDefaults()
   821  	// full flattening
   822  	opts.FlattenOpts.Minimal = false
   823  	assert.NoError(t, err)
   824  	appGen, err := newAppGenerator("JsonRefOperation", nil, nil, opts)
   825  	if assert.NoError(t, err) {
   826  		op, err := appGen.makeCodegenApp()
   827  		if assert.NoError(t, err) {
   828  			buf := bytes.NewBuffer(nil)
   829  			err := templates.MustGet("serverOperation").Execute(buf, op.Operations[0])
   830  			if assert.NoError(t, err) {
   831  				filecontent, err := appGen.GenOpts.LanguageOpts.FormatContent("operation.go", buf.Bytes())
   832  				if assert.NoError(t, err) {
   833  					res := string(filecontent)
   834  					assertInCode(t, "GetHealthCheck", res)
   835  				} else {
   836  					fmt.Println(buf.String())
   837  				}
   838  			}
   839  		}
   840  	}
   841  }
   842  
   843  func TestGenClientIssue890_ValidationFalseFlatteningTrue(t *testing.T) {
   844  	log.SetOutput(ioutil.Discard)
   845  	defer func() {
   846  		log.SetOutput(os.Stdout)
   847  		dr, _ := os.Getwd()
   848  		_ = os.RemoveAll(filepath.Join(filepath.FromSlash(dr), "restapi"))
   849  	}()
   850  	opts := testGenOpts()
   851  	opts.Spec = "../fixtures/bugs/890/swagger.yaml"
   852  	opts.ValidateSpec = false
   853  	// full flattening
   854  	opts.FlattenOpts.Minimal = false
   855  	// Testing this is enough as there is only one operation which is specified as $ref.
   856  	// If this doesn't get resolved then there will be an error definitely.
   857  	assert.NoError(t, GenerateClient("foo", nil, nil, &opts))
   858  }
   859  
   860  func TestGenServerIssue890_ValidationFalseFlattenFalse(t *testing.T) {
   861  	log.SetOutput(ioutil.Discard)
   862  	defer log.SetOutput(os.Stdout)
   863  	dr, _ := os.Getwd()
   864  	opts := &GenOpts{
   865  		Spec:              filepath.FromSlash("../fixtures/bugs/890/swagger.yaml"),
   866  		IncludeModel:      true,
   867  		IncludeValidator:  true,
   868  		IncludeHandler:    true,
   869  		IncludeParameters: true,
   870  		IncludeResponses:  true,
   871  		IncludeMain:       true,
   872  		ValidateSpec:      false,
   873  		APIPackage:        "restapi",
   874  		ModelPackage:      "model",
   875  		ServerPackage:     "server",
   876  		ClientPackage:     "client",
   877  		Target:            dr,
   878  		IsClient:          true,
   879  	}
   880  
   881  	//Testing Server Generation
   882  	err := opts.EnsureDefaults()
   883  	// minimal flattening
   884  	opts.FlattenOpts.Minimal = true
   885  	assert.NoError(t, err)
   886  	_, err = newAppGenerator("JsonRefOperation", nil, nil, opts)
   887  	// if flatten is not set, expand takes over so this would resume normally
   888  	assert.NoError(t, err)
   889  }
   890  
   891  func TestGenClientIssue890_ValidationFalseFlattenFalse(t *testing.T) {
   892  	log.SetOutput(ioutil.Discard)
   893  	defer func() {
   894  		dr, _ := os.Getwd()
   895  		_ = os.RemoveAll(filepath.Join(filepath.FromSlash(dr), "restapi"))
   896  		log.SetOutput(os.Stdout)
   897  	}()
   898  	opts := testGenOpts()
   899  	opts.Spec = "../fixtures/bugs/890/swagger.yaml"
   900  	opts.ValidateSpec = false
   901  	// minimal flattening
   902  	opts.FlattenOpts.Minimal = true
   903  	// Testing this is enough as there is only one operation which is specified as $ref.
   904  	// If this doesn't get resolved then there will be an error definitely.
   905  	// New: Now if flatten is false, expand takes over so server generation should resume normally
   906  	assert.NoError(t, GenerateClient("foo", nil, nil, &opts))
   907  }
   908  
   909  func TestGenServerIssue890_ValidationTrueFlattenFalse(t *testing.T) {
   910  	log.SetOutput(ioutil.Discard)
   911  	defer log.SetOutput(os.Stdout)
   912  	dr, _ := os.Getwd()
   913  	opts := &GenOpts{
   914  		Spec:              filepath.FromSlash("../fixtures/bugs/890/swagger.yaml"),
   915  		IncludeModel:      true,
   916  		IncludeValidator:  true,
   917  		IncludeHandler:    true,
   918  		IncludeParameters: true,
   919  		IncludeResponses:  true,
   920  		IncludeMain:       true,
   921  		ValidateSpec:      true,
   922  		APIPackage:        "restapi",
   923  		ModelPackage:      "model",
   924  		ServerPackage:     "server",
   925  		ClientPackage:     "client",
   926  		Target:            dr,
   927  		IsClient:          true,
   928  	}
   929  
   930  	//Testing Server Generation
   931  	err := opts.EnsureDefaults()
   932  	// minimal flattening
   933  	opts.FlattenOpts.Minimal = true
   934  	assert.NoError(t, err)
   935  	_, err = newAppGenerator("JsonRefOperation", nil, nil, opts)
   936  	// now if flatten is false, expand takes over so server generation should resume normally
   937  	assert.NoError(t, err)
   938  }
   939  
   940  func TestGenServerWithTemplate(t *testing.T) {
   941  	log.SetOutput(ioutil.Discard)
   942  	defer log.SetOutput(os.Stdout)
   943  	dr, _ := os.Getwd()
   944  
   945  	tests := []struct {
   946  		name      string
   947  		opts      *GenOpts
   948  		wantError bool
   949  	}{
   950  		{
   951  			name: "None_existing_contributor_tempalte",
   952  			opts: &GenOpts{
   953  				Spec:              filepath.FromSlash("../fixtures/bugs/890/swagger.yaml"),
   954  				IncludeModel:      true,
   955  				IncludeValidator:  true,
   956  				IncludeHandler:    true,
   957  				IncludeParameters: true,
   958  				IncludeResponses:  true,
   959  				IncludeMain:       true,
   960  				ValidateSpec:      true,
   961  				APIPackage:        "restapi",
   962  				ModelPackage:      "model",
   963  				ServerPackage:     "server",
   964  				ClientPackage:     "client",
   965  				Target:            dr,
   966  				IsClient:          true,
   967  				Template:          "InvalidTemplate",
   968  			},
   969  			wantError: true,
   970  		},
   971  		{
   972  			name: "Existing_contributor",
   973  			opts: &GenOpts{
   974  				Spec:              filepath.FromSlash("../fixtures/bugs/890/swagger.yaml"),
   975  				IncludeModel:      true,
   976  				IncludeValidator:  true,
   977  				IncludeHandler:    true,
   978  				IncludeParameters: true,
   979  				IncludeResponses:  true,
   980  				IncludeMain:       true,
   981  				ValidateSpec:      true,
   982  				APIPackage:        "restapi",
   983  				ModelPackage:      "model",
   984  				ServerPackage:     "server",
   985  				ClientPackage:     "client",
   986  				Target:            dr,
   987  				IsClient:          true,
   988  				Template:          "stratoscale",
   989  			},
   990  			wantError: false,
   991  		},
   992  	}
   993  
   994  	for _, tt := range tests {
   995  		t.Run(tt.name, func(t *testing.T) {
   996  			//Testing Server Generation
   997  			err := tt.opts.EnsureDefaults()
   998  			// minimal flattening
   999  			tt.opts.FlattenOpts.Minimal = true
  1000  			assert.NoError(t, err)
  1001  			_, err = newAppGenerator("JsonRefOperation", nil, nil, tt.opts)
  1002  			if tt.wantError {
  1003  				assert.Error(t, err)
  1004  			} else {
  1005  				assert.NoError(t, err)
  1006  			}
  1007  		})
  1008  	}
  1009  }
  1010  
  1011  func TestGenClientIssue890_ValidationTrueFlattenFalse(t *testing.T) {
  1012  	log.SetOutput(ioutil.Discard)
  1013  	defer func() {
  1014  		log.SetOutput(os.Stdout)
  1015  		dr, _ := os.Getwd()
  1016  		_ = os.RemoveAll(filepath.Join(filepath.FromSlash(dr), "restapi"))
  1017  	}()
  1018  	opts := testGenOpts()
  1019  	opts.Spec = filepath.FromSlash("../fixtures/bugs/890/swagger.yaml")
  1020  	opts.ValidateSpec = true
  1021  	// Testing this is enough as there is only one operation which is specified as $ref.
  1022  	// If this doesn't get resolved then there will be an error definitely.
  1023  	// same here: now if flatten doesn't resume, expand takes over
  1024  	assert.NoError(t, GenerateClient("foo", nil, nil, &opts))
  1025  }
  1026  
  1027  // This tests that securityDefinitions generate stable code
  1028  func TestBuilder_Issue1214(t *testing.T) {
  1029  	const any = `(.|\n)+`
  1030  	log.SetOutput(ioutil.Discard)
  1031  	defer log.SetOutput(os.Stdout)
  1032  	dr, _ := os.Getwd()
  1033  	opts := &GenOpts{
  1034  		Spec:              filepath.FromSlash("../fixtures/bugs/1214/fixture-1214.yaml"),
  1035  		IncludeModel:      true,
  1036  		IncludeValidator:  true,
  1037  		IncludeHandler:    true,
  1038  		IncludeParameters: true,
  1039  		IncludeResponses:  true,
  1040  		IncludeMain:       true,
  1041  		APIPackage:        "restapi",
  1042  		ModelPackage:      "model",
  1043  		ServerPackage:     "server",
  1044  		ClientPackage:     "client",
  1045  		Target:            dr,
  1046  		IsClient:          false,
  1047  	}
  1048  	err := opts.EnsureDefaults()
  1049  	assert.NoError(t, err)
  1050  	appGen, err := newAppGenerator("fixture-1214", nil, nil, opts)
  1051  	if assert.NoError(t, err) {
  1052  		op, err := appGen.makeCodegenApp()
  1053  		if assert.NoError(t, err) {
  1054  			for i := 0; i < 5; i++ {
  1055  				buf := bytes.NewBuffer(nil)
  1056  				ert := templates.MustGet("serverConfigureapi").Execute(buf, op)
  1057  				if assert.NoError(t, ert) {
  1058  					ff, erf := appGen.GenOpts.LanguageOpts.FormatContent("fixture_1214_configure_api.go", buf.Bytes())
  1059  					if assert.NoError(t, erf) {
  1060  						res := string(ff)
  1061  						assertRegexpInCode(t, any+
  1062  							`api\.AAuth = func\(user string, pass string\)`+any+
  1063  							`api\.BAuth = func\(token string\)`+any+
  1064  							`api\.CAuth = func\(token string\)`+any+
  1065  							`api\.DAuth = func\(token string\)`+any+
  1066  							`api\.EAuth = func\(token string, scopes \[\]string\)`+any, res)
  1067  					} else {
  1068  						fmt.Println(buf.String())
  1069  						break
  1070  					}
  1071  				} else {
  1072  					break
  1073  				}
  1074  				buf = bytes.NewBuffer(nil)
  1075  				err = templates.MustGet("serverBuilder").Execute(buf, op)
  1076  				if assert.NoError(t, err) {
  1077  					ff, err := appGen.GenOpts.LanguageOpts.FormatContent("fixture_1214_server.go", buf.Bytes())
  1078  					if assert.NoError(t, err) {
  1079  						res := string(ff)
  1080  						assertRegexpInCode(t, any+
  1081  							`AAuth: func\(user string, pass string\) \(interface{}, error\) {`+any+
  1082  							`BAuth: func\(token string\) \(interface{}, error\) {`+any+
  1083  							`CAuth: func\(token string\) \(interface{}, error\) {`+any+
  1084  							`DAuth: func\(token string\) \(interface{}, error\) {`+any+
  1085  							`EAuth: func\(token string, scopes \[\]string\) \(interface{}, error\) {`+any+
  1086  
  1087  							`AAuth func\(string, string\) \(interface{}, error\)`+any+
  1088  							`BAuth func\(string\) \(interface{}, error\)`+any+
  1089  							`CAuth func\(string\) \(interface{}, error\)`+any+
  1090  							`DAuth func\(string\) \(interface{}, error\)`+any+
  1091  							`EAuth func\(string, \[\]string\) \(interface{}, error\)`+any+
  1092  
  1093  							`if o\.AAuth == nil {`+any+
  1094  							`unregistered = append\(unregistered, "AAuth"\)`+any+
  1095  							`if o\.BAuth == nil {`+any+
  1096  							`unregistered = append\(unregistered, "K1Auth"\)`+any+
  1097  							`if o\.CAuth == nil {`+any+
  1098  							`unregistered = append\(unregistered, "K2Auth"\)`+any+
  1099  							`if o\.DAuth == nil {`+any+
  1100  							`unregistered = append\(unregistered, "K3Auth"\)`+any+
  1101  							`if o\.EAuth == nil {`+any+
  1102  							`unregistered = append\(unregistered, "EAuth"\)`+any+
  1103  
  1104  							`case "A":`+any+
  1105  							`case "B":`+any+
  1106  							`case "C":`+any+
  1107  							`case "D":`+any+
  1108  							`case "E":`+any, res)
  1109  					} else {
  1110  						fmt.Println(buf.String())
  1111  						break
  1112  					}
  1113  				} else {
  1114  					break
  1115  				}
  1116  			}
  1117  		}
  1118  	}
  1119  }
  1120  
  1121  func TestGenSecurityRequirements(t *testing.T) {
  1122  	for i := 0; i < 5; i++ {
  1123  		operation := "asecOp"
  1124  		b, err := opBuilder(operation, "../fixtures/bugs/1214/fixture-1214.yaml")
  1125  		if !assert.NoError(t, err) {
  1126  			t.FailNow()
  1127  			return
  1128  		}
  1129  		b.Security = b.Analyzed.SecurityRequirementsFor(&b.Operation)
  1130  		genRequirements := b.makeSecurityRequirements("o")
  1131  		assert.Len(t, genRequirements, 2)
  1132  		assert.Equal(t, []GenSecurityRequirements{
  1133  			{
  1134  				GenSecurityRequirement{
  1135  					Name:   "A",
  1136  					Scopes: []string{},
  1137  				},
  1138  				GenSecurityRequirement{
  1139  					Name:   "B",
  1140  					Scopes: []string{},
  1141  				},
  1142  				GenSecurityRequirement{
  1143  					Name:   "E",
  1144  					Scopes: []string{"s0", "s1", "s2", "s3", "s4"},
  1145  				},
  1146  			},
  1147  			{
  1148  				GenSecurityRequirement{
  1149  					Name:   "C",
  1150  					Scopes: []string{},
  1151  				},
  1152  				GenSecurityRequirement{
  1153  					Name:   "D",
  1154  					Scopes: []string{},
  1155  				},
  1156  				GenSecurityRequirement{
  1157  					Name:   "E",
  1158  					Scopes: []string{"s5", "s6", "s7", "s8", "s9"},
  1159  				},
  1160  			},
  1161  		}, genRequirements)
  1162  
  1163  		operation = "bsecOp"
  1164  		b, err = opBuilder(operation, "../fixtures/bugs/1214/fixture-1214.yaml")
  1165  		if !assert.NoError(t, err) {
  1166  			t.FailNow()
  1167  			return
  1168  		}
  1169  		b.Security = b.Analyzed.SecurityRequirementsFor(&b.Operation)
  1170  		genRequirements = b.makeSecurityRequirements("o")
  1171  		assert.Len(t, genRequirements, 2)
  1172  		assert.Equal(t, []GenSecurityRequirements{
  1173  			{
  1174  				GenSecurityRequirement{
  1175  					Name:   "A",
  1176  					Scopes: []string{},
  1177  				},
  1178  				GenSecurityRequirement{
  1179  					Name:   "E",
  1180  					Scopes: []string{"s0", "s1", "s2", "s3", "s4"},
  1181  				},
  1182  			},
  1183  			{
  1184  				GenSecurityRequirement{
  1185  					Name:   "D",
  1186  					Scopes: []string{},
  1187  				},
  1188  				GenSecurityRequirement{
  1189  					Name:   "E",
  1190  					Scopes: []string{"s5", "s6", "s7", "s8", "s9"},
  1191  				},
  1192  			},
  1193  		}, genRequirements)
  1194  	}
  1195  
  1196  	operation := "csecOp"
  1197  	b, err := opBuilder(operation, "../fixtures/bugs/1214/fixture-1214.yaml")
  1198  	if !assert.NoError(t, err) {
  1199  		t.FailNow()
  1200  		return
  1201  	}
  1202  	b.Security = b.Analyzed.SecurityRequirementsFor(&b.Operation)
  1203  	genRequirements := b.makeSecurityRequirements("o")
  1204  	assert.NotNil(t, genRequirements)
  1205  	assert.Len(t, genRequirements, 0)
  1206  
  1207  	operation = "nosecOp"
  1208  	b, err = opBuilder(operation, "../fixtures/bugs/1214/fixture-1214-2.yaml")
  1209  	if !assert.NoError(t, err) {
  1210  		t.FailNow()
  1211  		return
  1212  	}
  1213  	b.Security = b.Analyzed.SecurityRequirementsFor(&b.Operation)
  1214  	genRequirements = b.makeSecurityRequirements("o")
  1215  	assert.Nil(t, genRequirements)
  1216  }
  1217  
  1218  func TestGenerateServerOperation(t *testing.T) {
  1219  	log.SetOutput(ioutil.Discard)
  1220  	defer log.SetOutput(os.Stdout)
  1221  	fname := "../fixtures/codegen/todolist.simple.yml"
  1222  
  1223  	tgt, _ := ioutil.TempDir(filepath.Dir(fname), "generated")
  1224  	defer func() {
  1225  		_ = os.RemoveAll(tgt)
  1226  	}()
  1227  	o := &GenOpts{
  1228  		IncludeValidator:  true,
  1229  		ValidateSpec:      false,
  1230  		IncludeModel:      true,
  1231  		IncludeHandler:    true,
  1232  		IncludeParameters: true,
  1233  		IncludeResponses:  true,
  1234  		ModelPackage:      "models",
  1235  		Spec:              fname,
  1236  		Target:            tgt,
  1237  	}
  1238  	if err := o.EnsureDefaults(); err != nil {
  1239  		panic(err)
  1240  	}
  1241  
  1242  	err := GenerateServerOperation([]string{"createTask"}, nil)
  1243  	assert.Error(t, err)
  1244  
  1245  	d := o.TemplateDir
  1246  	o.TemplateDir = "./nowhere"
  1247  	err = GenerateServerOperation([]string{"notFound"}, o)
  1248  	assert.Error(t, err)
  1249  	o.TemplateDir = d
  1250  
  1251  	d = o.Spec
  1252  	o.Spec = "nowhere.yaml"
  1253  	err = GenerateServerOperation([]string{"notFound"}, o)
  1254  	assert.Error(t, err)
  1255  	o.Spec = d
  1256  
  1257  	err = GenerateServerOperation([]string{"notFound"}, o)
  1258  	assert.Error(t, err)
  1259  
  1260  	err = GenerateServerOperation([]string{"createTask"}, o)
  1261  	if !assert.NoError(t, err) {
  1262  		t.FailNow()
  1263  		return
  1264  	}
  1265  	// check expected files are generated and that's it
  1266  	_, err = os.Stat(filepath.Join(tgt, "tasks", "create_task.go"))
  1267  	assert.NoError(t, err)
  1268  	_, err = os.Stat(filepath.Join(tgt, "tasks", "create_task_parameters.go"))
  1269  	assert.NoError(t, err)
  1270  	_, err = os.Stat(filepath.Join(tgt, "tasks", "create_task_responses.go"))
  1271  	assert.NoError(t, err)
  1272  
  1273  	origStdout := os.Stdout
  1274  	defer func() {
  1275  		os.Stdout = origStdout
  1276  	}()
  1277  	os.Stdout, _ = os.Create(filepath.Join(tgt, "stdout"))
  1278  	o.DumpData = true
  1279  	// just checks this does not fail
  1280  	err = GenerateServerOperation([]string{"createTask"}, o)
  1281  	assert.NoError(t, err)
  1282  	_, err = os.Stat(filepath.Join(tgt, "stdout"))
  1283  	assert.NoError(t, err)
  1284  }
  1285  
  1286  // This tests that mimetypes generate stable code
  1287  func TestBuilder_Issue1646(t *testing.T) {
  1288  	log.SetOutput(ioutil.Discard)
  1289  	defer log.SetOutput(os.Stdout)
  1290  	dr, _ := os.Getwd()
  1291  	opts := &GenOpts{
  1292  		Spec:              filepath.FromSlash("../fixtures/bugs/1646/fixture-1646.yaml"),
  1293  		IncludeModel:      true,
  1294  		IncludeValidator:  true,
  1295  		IncludeHandler:    true,
  1296  		IncludeParameters: true,
  1297  		IncludeResponses:  true,
  1298  		IncludeMain:       true,
  1299  		APIPackage:        "restapi",
  1300  		ModelPackage:      "model",
  1301  		ServerPackage:     "server",
  1302  		ClientPackage:     "client",
  1303  		Target:            dr,
  1304  		IsClient:          false,
  1305  	}
  1306  	err := opts.EnsureDefaults()
  1307  	assert.NoError(t, err)
  1308  	appGen, err := newAppGenerator("fixture-1646", nil, nil, opts)
  1309  
  1310  	if assert.NoError(t, err) {
  1311  		preCons, preConj := appGen.makeConsumes()
  1312  		preProds, preProdj := appGen.makeProduces()
  1313  		assert.True(t, preConj)
  1314  		assert.True(t, preProdj)
  1315  		for i := 0; i < 5; i++ {
  1316  			cons, conj := appGen.makeConsumes()
  1317  			prods, prodj := appGen.makeProduces()
  1318  			assert.True(t, conj)
  1319  			assert.True(t, prodj)
  1320  			assert.Equal(t, preConj, conj)
  1321  			assert.Equal(t, preProdj, prodj)
  1322  			assert.Equal(t, preCons, cons)
  1323  			assert.Equal(t, preProds, prods)
  1324  		}
  1325  	}
  1326  }
  1327  
  1328  func TestGenServer_StrictAdditionalProperties(t *testing.T) {
  1329  	log.SetOutput(ioutil.Discard)
  1330  	defer log.SetOutput(os.Stdout)
  1331  	dr, _ := os.Getwd()
  1332  	opts := &GenOpts{
  1333  		Spec:              filepath.FromSlash("../fixtures/codegen/strict-additional-properties.yml"),
  1334  		IncludeModel:      true,
  1335  		IncludeValidator:  true,
  1336  		IncludeHandler:    true,
  1337  		IncludeParameters: true,
  1338  		IncludeResponses:  true,
  1339  		IncludeMain:       true,
  1340  		APIPackage:        "restapi",
  1341  		ModelPackage:      "model",
  1342  		ServerPackage:     "server",
  1343  		ClientPackage:     "client",
  1344  		Target:            dr,
  1345  		IsClient:          false,
  1346  	}
  1347  	if err := opts.EnsureDefaults(); err != nil {
  1348  		panic(err)
  1349  	}
  1350  
  1351  	opts.StrictAdditionalProperties = true
  1352  
  1353  	appGen, err := newAppGenerator("StrictAdditionalProperties", nil, nil, opts)
  1354  	if assert.NoError(t, err) {
  1355  		op, err := appGen.makeCodegenApp()
  1356  		if assert.NoError(t, err) {
  1357  			buf := bytes.NewBuffer(nil)
  1358  			err := templates.MustGet("serverOperation").Execute(buf, op.Operations[0])
  1359  			if assert.NoError(t, err) {
  1360  				ff, err := appGen.GenOpts.LanguageOpts.FormatContent("strictAdditionalProperties.go", buf.Bytes())
  1361  				if assert.NoError(t, err) {
  1362  					res := string(ff)
  1363  					for _, tt := range []struct {
  1364  						name      string
  1365  						assertion func(testing.TB, string, string) bool
  1366  					}{
  1367  						{"PostTestBody", assertInCode},
  1368  						{"PostTestParamsBodyExplicit", assertInCode},
  1369  						{"PostTestParamsBodyImplicit", assertInCode},
  1370  						{"PostTestParamsBodyDisabled", assertNotInCode},
  1371  					} {
  1372  						fn := funcBody(res, "*"+tt.name+") UnmarshalJSON(data []byte) error")
  1373  						if assert.NotEmpty(t, fn, "Method UnmarshalJSON should be defined for type *"+tt.name) {
  1374  							tt.assertion(t, "dec.DisallowUnknownFields()", fn)
  1375  						}
  1376  					}
  1377  				} else {
  1378  					fmt.Println(buf.String())
  1379  				}
  1380  			}
  1381  		}
  1382  	}
  1383  }