github.com/emreu/go-swagger@v0.22.1/generator/client_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  	"io/ioutil"
    19  	"log"
    20  	"os"
    21  	"path/filepath"
    22  	"strings"
    23  	"testing"
    24  
    25  	"github.com/stretchr/testify/assert"
    26  )
    27  
    28  const (
    29  	defaultAPIPackage    = "operations"
    30  	defaultClientPackage = "client"
    31  	defaultModelPackage  = "models"
    32  	defaultServerPackage = "restapi"
    33  
    34  	basicFixture = "../fixtures/petstores/petstore.json"
    35  )
    36  
    37  func testClientGenOpts() (g GenOpts) {
    38  	g.Target = "."
    39  	g.APIPackage = defaultAPIPackage
    40  	g.ModelPackage = defaultModelPackage
    41  	g.ServerPackage = defaultServerPackage
    42  	g.ClientPackage = defaultClientPackage
    43  	g.Principal = ""
    44  	g.DefaultScheme = "http"
    45  	g.IncludeModel = true
    46  	g.IncludeValidator = true
    47  	g.IncludeHandler = true
    48  	g.IncludeParameters = true
    49  	g.IncludeResponses = true
    50  	g.IncludeSupport = true
    51  	g.TemplateDir = ""
    52  	g.DumpData = false
    53  	g.IsClient = true
    54  	_ = g.EnsureDefaults()
    55  	return
    56  }
    57  
    58  func Test_GenerateClient(t *testing.T) {
    59  	log.SetOutput(ioutil.Discard)
    60  
    61  	// exercise safeguards
    62  	err := GenerateClient("test", []string{"model1"}, []string{"op1", "op2"}, nil)
    63  	assert.Error(t, err)
    64  
    65  	opts := testClientGenOpts()
    66  	opts.TemplateDir = "dir/nowhere"
    67  	err = GenerateClient("test", []string{"model1"}, []string{"op1", "op2"}, &opts)
    68  	assert.Error(t, err)
    69  
    70  	opts = testClientGenOpts()
    71  	opts.TemplateDir = "http://nowhere.com"
    72  	err = GenerateClient("test", []string{"model1"}, []string{"op1", "op2"}, &opts)
    73  	assert.Error(t, err)
    74  
    75  	opts = testClientGenOpts()
    76  	opts.Spec = "dir/nowhere.yaml"
    77  	err = GenerateClient("test", []string{"model1"}, []string{"op1", "op2"}, &opts)
    78  	assert.Error(t, err)
    79  
    80  	opts = testClientGenOpts()
    81  	opts.Spec = basicFixture
    82  	err = GenerateClient("test", []string{"model1"}, []string{}, &opts)
    83  	assert.Error(t, err)
    84  
    85  	opts = testClientGenOpts()
    86  	// bad content in spec (HTML...)
    87  	opts.Spec = "https://github.com/OAI/OpenAPI-Specification/blob/master/examples/v2.0/json/petstore.json"
    88  	err = GenerateClient("test", []string{}, []string{}, &opts)
    89  	assert.Error(t, err)
    90  
    91  	opts = testClientGenOpts()
    92  	// generate remote spec
    93  	opts.Spec = "https://raw.githubusercontent.com/OAI/OpenAPI-Specification/master/examples/v2.0/yaml/petstore.yaml"
    94  	cwd, _ := os.Getwd()
    95  	tft, _ := ioutil.TempDir(cwd, "generated")
    96  	defer func() {
    97  		_ = os.RemoveAll(tft)
    98  	}()
    99  	opts.Target = tft
   100  	opts.IsClient = true
   101  	DefaultSectionOpts(&opts)
   102  
   103  	defer func() {
   104  		_ = os.RemoveAll(opts.Target)
   105  	}()
   106  	err = GenerateClient("test", []string{}, []string{}, &opts)
   107  	assert.NoError(t, err)
   108  
   109  	// just checks this does not fail
   110  	origStdout := os.Stdout
   111  	defer func() {
   112  		os.Stdout = origStdout
   113  	}()
   114  	tgt, _ := ioutil.TempDir(cwd, "dumped")
   115  	defer func() {
   116  		_ = os.RemoveAll(tgt)
   117  	}()
   118  	os.Stdout, _ = os.Create(filepath.Join(tgt, "stdout"))
   119  	opts.DumpData = true
   120  	err = GenerateClient("test", []string{}, []string{}, &opts)
   121  	assert.NoError(t, err)
   122  	_, err = os.Stat(filepath.Join(tgt, "stdout"))
   123  	assert.NoError(t, err)
   124  }
   125  
   126  func TestClient(t *testing.T) {
   127  	targetdir, err := ioutil.TempDir(os.TempDir(), "swagger_nogo")
   128  	if err != nil {
   129  		t.Fatalf("Failed to create a test target directory: %v", err)
   130  	}
   131  	log.SetOutput(ioutil.Discard)
   132  	defer func() {
   133  		_ = os.RemoveAll(targetdir)
   134  		log.SetOutput(os.Stdout)
   135  	}()
   136  
   137  	tests := []struct {
   138  		name      string
   139  		template  string
   140  		wantError bool
   141  		prepare   func(opts *GenOpts)
   142  	}{
   143  		{
   144  			name:      "InvalidSpec",
   145  			wantError: true,
   146  			prepare: func(opts *GenOpts) {
   147  				opts.Spec = invalidSpecExample
   148  				opts.ValidateSpec = true
   149  			},
   150  		},
   151  		{
   152  			name:      "BaseImportDisabled",
   153  			wantError: false,
   154  		},
   155  		{
   156  			name:      "Non_existing_contributor_template",
   157  			template:  "NonExistingContributorTemplate",
   158  			wantError: true,
   159  		},
   160  		{
   161  			name:      "Existing_contributor",
   162  			template:  "stratoscale",
   163  			wantError: false,
   164  		},
   165  	}
   166  
   167  	for _, tt := range tests {
   168  		t.Run(tt.name, func(t *testing.T) {
   169  			opts := testClientGenOpts()
   170  			opts.Target = targetdir
   171  			opts.Spec = basicFixture
   172  			opts.LanguageOpts.BaseImportFunc = nil
   173  			opts.Template = tt.template
   174  
   175  			if tt.prepare != nil {
   176  				tt.prepare(&opts)
   177  			}
   178  
   179  			err := GenerateClient("foo", nil, nil, &opts)
   180  			if tt.wantError {
   181  				assert.Error(t, err)
   182  			} else {
   183  				assert.NoError(t, err)
   184  			}
   185  		})
   186  	}
   187  }
   188  
   189  func TestGenClient_1518(t *testing.T) {
   190  	// test client response handling when unexpected success response kicks in
   191  	log.SetOutput(ioutil.Discard)
   192  	defer func() {
   193  		log.SetOutput(os.Stdout)
   194  	}()
   195  
   196  	opts := testClientGenOpts()
   197  	opts.Spec = filepath.Join("..", "fixtures", "bugs", "1518", "fixture-1518.yaml")
   198  
   199  	cwd, _ := os.Getwd()
   200  	tft, _ := ioutil.TempDir(cwd, "generated")
   201  	opts.Target = tft
   202  
   203  	defer func() {
   204  		_ = os.RemoveAll(opts.Target)
   205  	}()
   206  	err := GenerateClient("client", []string{}, []string{}, &opts)
   207  	if !assert.NoError(t, err) {
   208  		t.FailNow()
   209  	}
   210  
   211  	fixtureConfig := map[string][]string{
   212  		"client/operations/operations_client.go": { // generated file
   213  			// expected code lines
   214  			`success, ok := result.(*GetRecords1OK)`,
   215  			`if ok {`,
   216  			`return success, nil`,
   217  			`msg := fmt.Sprintf(`,
   218  			`panic(msg)`,
   219  			// expected code lines
   220  			`success, ok := result.(*GetRecords2OK)`,
   221  			`if ok {`,
   222  			`return success, nil`,
   223  			`unexpectedSuccess := result.(*GetRecords2Default)`,
   224  			`return nil, runtime.NewAPIError("unexpected success response: content available as default response in error", unexpectedSuccess, unexpectedSuccess.Code())`,
   225  			// expected code lines
   226  			`switch value := result.(type) {`,
   227  			`case *GetRecords3OK:`,
   228  			`return value, nil, nil`,
   229  			`case *GetRecords3Created:`,
   230  			`return nil, value, nil`,
   231  			`msg := fmt.Sprintf(`,
   232  			`panic(msg)`,
   233  			// expected code lines
   234  			`switch value := result.(type) {`,
   235  			`case *GetRecords4OK:`,
   236  			`return value, nil, nil`,
   237  			`case *GetRecords4Created:`,
   238  			`return nil, value, nil`,
   239  			`unexpectedSuccess := result.(*GetRecords4Default)`,
   240  			`return nil, nil, runtime.NewAPIError("unexpected success response: content available as default response in error", unexpectedSuccess, unexpectedSuccess.Code())`,
   241  		},
   242  	}
   243  
   244  	for fileToInspect, expectedCode := range fixtureConfig {
   245  		code, err := ioutil.ReadFile(filepath.Join(opts.Target, filepath.FromSlash(fileToInspect)))
   246  		if assert.NoError(t, err) {
   247  			for line, codeLine := range expectedCode {
   248  				if !assertInCode(t, strings.TrimSpace(codeLine), string(code)) {
   249  					t.Logf("Code expected did not match in codegenfile %s for expected line %d: %q", fileToInspect, line, expectedCode[line])
   250  				}
   251  			}
   252  		}
   253  	}
   254  }