github.com/wangyougui/gf/v2@v2.6.5/net/goai/goai_z_unit_test.go (about)

     1  // Copyright GoFrame Author(https://goframe.org). All Rights Reserved.
     2  //
     3  // This Source Code Form is subject to the terms of the MIT License.
     4  // If a copy of the MIT was not distributed with this file,
     5  // You can obtain one at https://github.com/wangyougui/gf.
     6  
     7  package goai_test
     8  
     9  import (
    10  	"context"
    11  	"fmt"
    12  	"net/http"
    13  	"testing"
    14  
    15  	"github.com/wangyougui/gf/v2/encoding/gjson"
    16  	"github.com/wangyougui/gf/v2/frame/g"
    17  	"github.com/wangyougui/gf/v2/internal/json"
    18  	"github.com/wangyougui/gf/v2/net/goai"
    19  	"github.com/wangyougui/gf/v2/test/gtest"
    20  	"github.com/wangyougui/gf/v2/util/gmeta"
    21  	"github.com/wangyougui/gf/v2/util/gtag"
    22  )
    23  
    24  func Test_Basic(t *testing.T) {
    25  	type CommonReq struct {
    26  		AppId      int64  `json:"appId" v:"required" in:"cookie" description:"应用Id"`
    27  		ResourceId string `json:"resourceId" in:"query" description:"资源Id"`
    28  	}
    29  	type SetSpecInfo struct {
    30  		StorageType string   `v:"required|in:CLOUD_PREMIUM,CLOUD_SSD,CLOUD_HSSD" description:"StorageType"`
    31  		Shards      int32    `description:"shards 分片数"`
    32  		Params      []string `description:"默认参数(json 串-ClickHouseParams)"`
    33  	}
    34  	type CreateResourceReq struct {
    35  		CommonReq
    36  		gmeta.Meta `path:"/CreateResourceReq" method:"POST" tags:"default"`
    37  		Name       string                  `description:"实例名称"`
    38  		Product    string                  `description:"业务类型"`
    39  		Region     string                  `v:"required" description:"区域"`
    40  		SetMap     map[string]*SetSpecInfo `v:"required" description:"配置Map"`
    41  		SetSlice   []SetSpecInfo           `v:"required" description:"配置Slice"`
    42  	}
    43  
    44  	gtest.C(t, func(t *gtest.T) {
    45  		var (
    46  			err error
    47  			oai = goai.New()
    48  			req = new(CreateResourceReq)
    49  		)
    50  		err = oai.Add(goai.AddInput{
    51  			Object: req,
    52  		})
    53  		t.AssertNil(err)
    54  		// Schema asserts.
    55  		t.Assert(len(oai.Components.Schemas.Map()), 2)
    56  		t.Assert(oai.Components.Schemas.Get(`github.com.gogf.gf.v2.net.goai_test.CreateResourceReq`).Value.Type, goai.TypeObject)
    57  		t.Assert(len(oai.Components.Schemas.Get(`github.com.gogf.gf.v2.net.goai_test.CreateResourceReq`).Value.Properties.Map()), 7)
    58  		t.Assert(oai.Components.Schemas.Get(`github.com.gogf.gf.v2.net.goai_test.CreateResourceReq`).Value.Properties.Get(`appId`).Value.Type, goai.TypeInteger)
    59  		t.Assert(oai.Components.Schemas.Get(`github.com.gogf.gf.v2.net.goai_test.CreateResourceReq`).Value.Properties.Get(`resourceId`).Value.Type, goai.TypeString)
    60  
    61  		t.Assert(len(oai.Components.Schemas.Get(`github.com.gogf.gf.v2.net.goai_test.SetSpecInfo`).Value.Properties.Map()), 3)
    62  		t.Assert(oai.Components.Schemas.Get(`github.com.gogf.gf.v2.net.goai_test.SetSpecInfo`).Value.Properties.Get(`Params`).Value.Type, goai.TypeArray)
    63  	})
    64  }
    65  
    66  func TestOpenApiV3_Add(t *testing.T) {
    67  	type CommonReq struct {
    68  		AppId      int64  `json:"appId" v:"required" in:"path" description:"应用Id"`
    69  		ResourceId string `json:"resourceId" in:"query" description:"资源Id"`
    70  	}
    71  	type SetSpecInfo struct {
    72  		StorageType string   `v:"required|in:CLOUD_PREMIUM,CLOUD_SSD,CLOUD_HSSD" description:"StorageType"`
    73  		Shards      int32    `description:"shards 分片数"`
    74  		Params      []string `description:"默认参数(json 串-ClickHouseParams)"`
    75  	}
    76  	type CreateResourceReq struct {
    77  		CommonReq
    78  		gmeta.Meta `path:"/CreateResourceReq" method:"POST" tags:"default"`
    79  		Name       string                  `description:"实例名称"`
    80  		Product    string                  `description:"业务类型"`
    81  		Region     string                  `v:"required" description:"区域"`
    82  		SetMap     map[string]*SetSpecInfo `v:"required" description:"配置Map"`
    83  		SetSlice   []SetSpecInfo           `v:"required" description:"配置Slice"`
    84  	}
    85  
    86  	type CreateResourceRes struct {
    87  		gmeta.Meta `description:"Demo Response Struct"`
    88  		FlowId     int64 `description:"创建实例流程id"`
    89  	}
    90  
    91  	f := func(ctx context.Context, req *CreateResourceReq) (res *CreateResourceRes, err error) {
    92  		return
    93  	}
    94  
    95  	gtest.C(t, func(t *gtest.T) {
    96  		var (
    97  			err error
    98  			oai = goai.New()
    99  		)
   100  		err = oai.Add(goai.AddInput{
   101  			Path:   "/test1/{appId}",
   102  			Method: http.MethodPut,
   103  			Object: f,
   104  		})
   105  		t.AssertNil(err)
   106  
   107  		err = oai.Add(goai.AddInput{
   108  			Path:   "/test1/{appId}",
   109  			Method: http.MethodPost,
   110  			Object: f,
   111  		})
   112  		t.AssertNil(err)
   113  		// fmt.Println(oai.String())
   114  		// Schema asserts.
   115  		t.Assert(len(oai.Components.Schemas.Map()), 3)
   116  		t.Assert(oai.Components.Schemas.Get(`github.com.gogf.gf.v2.net.goai_test.CreateResourceReq`).Value.Type, goai.TypeObject)
   117  
   118  		t.Assert(len(oai.Components.Schemas.Get(`github.com.gogf.gf.v2.net.goai_test.CreateResourceReq`).Value.Properties.Map()), 7)
   119  		t.Assert(len(oai.Paths["/test1/{appId}"].Put.RequestBody.Value.Content["application/json"].Schema.Value.Properties.Map()), 5)
   120  		t.Assert(len(oai.Paths["/test1/{appId}"].Post.RequestBody.Value.Content["application/json"].Schema.Value.Properties.Map()), 5)
   121  
   122  		t.Assert(oai.Paths["/test1/{appId}"].Post.Parameters[0].Value.Schema.Value.Type, goai.TypeInteger)
   123  		t.Assert(oai.Paths["/test1/{appId}"].Post.Parameters[1].Value.Schema.Value.Type, goai.TypeString)
   124  
   125  		t.Assert(len(oai.Components.Schemas.Get(`github.com.gogf.gf.v2.net.goai_test.SetSpecInfo`).Value.Properties.Map()), 3)
   126  		t.Assert(oai.Components.Schemas.Get(`github.com.gogf.gf.v2.net.goai_test.SetSpecInfo`).Value.Properties.Get(`Params`).Value.Type, goai.TypeArray)
   127  
   128  		// Paths.
   129  		t.Assert(len(oai.Paths), 1)
   130  		t.AssertNE(oai.Paths[`/test1/{appId}`].Put, nil)
   131  		t.Assert(len(oai.Paths[`/test1/{appId}`].Put.Tags), 1)
   132  		t.Assert(len(oai.Paths[`/test1/{appId}`].Put.Parameters), 2)
   133  		t.AssertNE(oai.Paths[`/test1/{appId}`].Post, nil)
   134  		t.Assert(len(oai.Paths[`/test1/{appId}`].Post.Tags), 1)
   135  		t.Assert(len(oai.Paths[`/test1/{appId}`].Post.Parameters), 2)
   136  	})
   137  }
   138  
   139  func TestOpenApiV3_Add_Recursive(t *testing.T) {
   140  	type CategoryTreeItem struct {
   141  		Id       uint                `json:"id"`
   142  		ParentId uint                `json:"parent_id"`
   143  		Items    []*CategoryTreeItem `json:"items,omitempty"`
   144  	}
   145  
   146  	type CategoryGetTreeReq struct {
   147  		gmeta.Meta  `path:"/category-get-tree" method:"GET" tags:"default"`
   148  		ContentType string `in:"query"`
   149  	}
   150  	type CategoryGetTreeRes struct {
   151  		List []*CategoryTreeItem
   152  	}
   153  
   154  	f := func(ctx context.Context, req *CategoryGetTreeReq) (res *CategoryGetTreeRes, err error) {
   155  		return
   156  	}
   157  
   158  	gtest.C(t, func(t *gtest.T) {
   159  		var (
   160  			err error
   161  			oai = goai.New()
   162  		)
   163  		err = oai.Add(goai.AddInput{
   164  			Path:   "/tree",
   165  			Object: f,
   166  		})
   167  		t.AssertNil(err)
   168  		// Schema asserts.
   169  		t.Assert(len(oai.Components.Schemas.Map()), 3)
   170  		t.Assert(oai.Components.Schemas.Get(`github.com.gogf.gf.v2.net.goai_test.CategoryTreeItem`).Value.Type, goai.TypeObject)
   171  		t.Assert(len(oai.Components.Schemas.Get(`github.com.gogf.gf.v2.net.goai_test.CategoryTreeItem`).Value.Properties.Map()), 3)
   172  	})
   173  }
   174  
   175  func TestOpenApiV3_Add_EmptyReqAndRes(t *testing.T) {
   176  	type CaptchaIndexReq struct {
   177  		gmeta.Meta `method:"PUT" summary:"获取默认的验证码" description:"注意直接返回的是图片二进制内容" tags:"前台-验证码"`
   178  	}
   179  	type CaptchaIndexRes struct {
   180  		gmeta.Meta `mime:"png" description:"验证码二进制内容" `
   181  	}
   182  
   183  	f := func(ctx context.Context, req *CaptchaIndexReq) (res *CaptchaIndexRes, err error) {
   184  		return
   185  	}
   186  
   187  	gtest.C(t, func(t *gtest.T) {
   188  		var (
   189  			err error
   190  			oai = goai.New()
   191  		)
   192  		err = oai.Add(goai.AddInput{
   193  			Path:   "/tree",
   194  			Object: f,
   195  		})
   196  		t.AssertNil(err)
   197  		// Schema asserts.
   198  		fmt.Println(oai.String())
   199  	})
   200  }
   201  
   202  func TestOpenApiV3_Add_AutoDetectIn(t *testing.T) {
   203  	type Req struct {
   204  		gmeta.Meta `method:"get" tags:"default"`
   205  		Name       string
   206  		Product    string
   207  		Region     string
   208  	}
   209  
   210  	type Res struct {
   211  		gmeta.Meta `description:"Demo Response Struct"`
   212  	}
   213  
   214  	f := func(ctx context.Context, req *Req) (res *Res, err error) {
   215  		return
   216  	}
   217  
   218  	gtest.C(t, func(t *gtest.T) {
   219  		var (
   220  			err  error
   221  			oai  = goai.New()
   222  			path = `/test/{product}/{name}`
   223  		)
   224  		err = oai.Add(goai.AddInput{
   225  			Path:   path,
   226  			Method: http.MethodGet,
   227  			Object: f,
   228  		})
   229  		t.AssertNil(err)
   230  
   231  		fmt.Println(oai.String())
   232  
   233  		t.Assert(len(oai.Components.Schemas.Map()), 2)
   234  		t.Assert(len(oai.Paths), 1)
   235  		t.AssertNE(oai.Paths[path].Get, nil)
   236  		t.Assert(len(oai.Paths[path].Get.Parameters), 3)
   237  		t.Assert(oai.Paths[path].Get.Parameters[0].Value.Name, `Name`)
   238  		t.Assert(oai.Paths[path].Get.Parameters[0].Value.In, goai.ParameterInPath)
   239  		t.Assert(oai.Paths[path].Get.Parameters[1].Value.Name, `Product`)
   240  		t.Assert(oai.Paths[path].Get.Parameters[1].Value.In, goai.ParameterInPath)
   241  		t.Assert(oai.Paths[path].Get.Parameters[2].Value.Name, `Region`)
   242  		t.Assert(oai.Paths[path].Get.Parameters[2].Value.In, goai.ParameterInQuery)
   243  	})
   244  }
   245  
   246  func TestOpenApiV3_CommonRequest(t *testing.T) {
   247  	type CommonRequest struct {
   248  		Code    int         `json:"code"    description:"Error code"`
   249  		Message string      `json:"message" description:"Error message"`
   250  		Data    interface{} `json:"data"    description:"Result data for certain request according API definition"`
   251  	}
   252  
   253  	type Req struct {
   254  		gmeta.Meta `method:"PUT"`
   255  		Product    string `json:"product" v:"required" description:"Unique product key"`
   256  		Name       string `json:"name"    v:"required" description:"Instance name"`
   257  	}
   258  	type Res struct {
   259  		Product      string `json:"product"      v:"required" description:"Unique product key"`
   260  		TemplateName string `json:"templateName" v:"required" description:"Workflow template name"`
   261  		Version      string `json:"version"      v:"required" description:"Workflow template version"`
   262  		TxID         string `json:"txID"         v:"required" description:"Transaction ID for creating instance"`
   263  		Globals      string `json:"globals"                   description:"Globals"`
   264  	}
   265  
   266  	f := func(ctx context.Context, req *Req) (res *Res, err error) {
   267  		return
   268  	}
   269  
   270  	gtest.C(t, func(t *gtest.T) {
   271  		var (
   272  			err error
   273  			oai = goai.New()
   274  		)
   275  
   276  		oai.Config.CommonRequest = CommonRequest{}
   277  		oai.Config.CommonRequestDataField = `Data`
   278  
   279  		err = oai.Add(goai.AddInput{
   280  			Path:   "/index",
   281  			Object: f,
   282  		})
   283  		t.AssertNil(err)
   284  		// Schema asserts.
   285  		t.Assert(len(oai.Components.Schemas.Map()), 3)
   286  		t.Assert(len(oai.Paths), 1)
   287  		t.Assert(len(oai.Paths["/index"].Put.RequestBody.Value.Content["application/json"].Schema.Value.Properties.Map()), 3)
   288  	})
   289  }
   290  
   291  func TestOpenApiV3_CommonRequest_WithoutDataField_Setting(t *testing.T) {
   292  	type CommonRequest struct {
   293  		Code    int         `json:"code"    description:"Error code"`
   294  		Message string      `json:"message" description:"Error message"`
   295  		Data    interface{} `json:"data"    description:"Result data for certain request according API definition"`
   296  	}
   297  
   298  	type PutReq struct {
   299  		gmeta.Meta `method:"PUT"`
   300  		Product    string `json:"product" in:"query" v:"required" description:"Unique product key"`
   301  		Name       string `json:"name"    in:"query"  v:"required" description:"Instance name"`
   302  	}
   303  
   304  	type PostReq struct {
   305  		gmeta.Meta `method:"POST"`
   306  		Product    string `json:"product" v:"required" description:"Unique product key"`
   307  		Name       string `json:"name"    v:"required" description:"Instance name"`
   308  	}
   309  
   310  	type Res struct {
   311  		Product      string `json:"product"      v:"required" description:"Unique product key"`
   312  		TemplateName string `json:"templateName" v:"required" description:"Workflow template name"`
   313  		Version      string `json:"version"      v:"required" description:"Workflow template version"`
   314  		TxID         string `json:"txID"         v:"required" description:"Transaction ID for creating instance"`
   315  		Globals      string `json:"globals"                   description:"Globals"`
   316  	}
   317  
   318  	f := func(ctx context.Context, req *PutReq) (res *Res, err error) {
   319  		return
   320  	}
   321  	f2 := func(ctx context.Context, req *PostReq) (res *Res, err error) {
   322  		return
   323  	}
   324  
   325  	gtest.C(t, func(t *gtest.T) {
   326  		var (
   327  			err error
   328  			oai = goai.New()
   329  		)
   330  
   331  		oai.Config.CommonRequest = CommonRequest{}
   332  
   333  		err = oai.Add(goai.AddInput{
   334  			Path:   "/index",
   335  			Object: f,
   336  		})
   337  		t.AssertNil(err)
   338  
   339  		err = oai.Add(goai.AddInput{
   340  			Path:   "/index",
   341  			Object: f2,
   342  		})
   343  		t.AssertNil(err)
   344  		// Schema asserts.
   345  		// fmt.Println(oai.String())
   346  		t.Assert(len(oai.Components.Schemas.Map()), 4)
   347  		t.Assert(len(oai.Paths), 1)
   348  		t.Assert(len(oai.Paths["/index"].Put.Parameters), 2)
   349  		t.Assert(len(oai.Paths["/index"].Put.RequestBody.Value.Content["application/json"].Schema.Value.Properties.Map()), 3)
   350  		t.Assert(len(oai.Paths["/index"].Post.Parameters), 0)
   351  		t.Assert(len(oai.Paths["/index"].Post.RequestBody.Value.Content["application/json"].Schema.Value.Properties.Map()), 5)
   352  	})
   353  }
   354  
   355  func TestOpenApiV3_CommonRequest_EmptyRequest(t *testing.T) {
   356  	type CommonRequest struct {
   357  		Code    int         `json:"code"    description:"Error code"`
   358  		Message string      `json:"message" description:"Error message"`
   359  		Data    interface{} `json:"data"    description:"Result data for certain request according API definition"`
   360  	}
   361  
   362  	type Req struct {
   363  		gmeta.Meta `method:"Put"`
   364  		Product    string `json:"product" in:"query" v:"required" description:"Unique product key"`
   365  		Name       string `json:"name"    in:"query"  v:"required" description:"Instance name"`
   366  	}
   367  	type Res struct{}
   368  
   369  	f := func(ctx context.Context, req *Req) (res *Res, err error) {
   370  		return
   371  	}
   372  
   373  	gtest.C(t, func(t *gtest.T) {
   374  		var (
   375  			err error
   376  			oai = goai.New()
   377  		)
   378  
   379  		oai.Config.CommonRequest = CommonRequest{}
   380  		oai.Config.CommonRequestDataField = `Data`
   381  
   382  		err = oai.Add(goai.AddInput{
   383  			Path:   "/index",
   384  			Object: f,
   385  		})
   386  		t.AssertNil(err)
   387  		// Schema asserts.
   388  		// fmt.Println(oai.String())
   389  		t.Assert(len(oai.Components.Schemas.Map()), 3)
   390  		t.Assert(len(oai.Paths), 1)
   391  		t.Assert(len(oai.Paths["/index"].Put.RequestBody.Value.Content["application/json"].Schema.Value.Properties.Map()), 3)
   392  	})
   393  }
   394  
   395  func TestOpenApiV3_CommonRequest_SubDataField(t *testing.T) {
   396  	type CommonReqError struct {
   397  		Code    string `description:"错误码"`
   398  		Message string `description:"错误描述"`
   399  	}
   400  
   401  	type CommonReqRequest struct {
   402  		RequestId string          `description:"RequestId"`
   403  		Error     *CommonReqError `json:",omitempty" description:"执行错误信息"`
   404  	}
   405  
   406  	type CommonReq struct {
   407  		Request CommonReqRequest
   408  	}
   409  
   410  	type PutReq struct {
   411  		gmeta.Meta `method:"Put"`
   412  		Product    string `json:"product" in:"query" v:"required" description:"Unique product key"`
   413  		Name       string `json:"name"    in:"query"  v:"required" description:"Instance name"`
   414  	}
   415  
   416  	type PostReq struct {
   417  		gmeta.Meta `method:"Post"`
   418  		Product    string `json:"product" v:"required" description:"Unique product key"`
   419  		Name       string `json:"name"    v:"required" description:"Instance name"`
   420  	}
   421  
   422  	type Res struct {
   423  		Product      string `json:"product"      v:"required" description:"Unique product key"`
   424  		TemplateName string `json:"templateName" v:"required" description:"Workflow template name"`
   425  		Version      string `json:"version"      v:"required" description:"Workflow template version"`
   426  		TxID         string `json:"txID"         v:"required" description:"Transaction ID for creating instance"`
   427  		Globals      string `json:"globals"                   description:"Globals"`
   428  	}
   429  
   430  	f := func(ctx context.Context, req *PutReq) (res *Res, err error) {
   431  		return
   432  	}
   433  	f2 := func(ctx context.Context, req *PostReq) (res *Res, err error) {
   434  		return
   435  	}
   436  
   437  	gtest.C(t, func(t *gtest.T) {
   438  		var (
   439  			err error
   440  			oai = goai.New()
   441  		)
   442  
   443  		oai.Config.CommonRequest = CommonReq{}
   444  		oai.Config.CommonRequestDataField = `Request.`
   445  
   446  		err = oai.Add(goai.AddInput{
   447  			Path:   "/index",
   448  			Object: f,
   449  		})
   450  		t.AssertNil(err)
   451  
   452  		err = oai.Add(goai.AddInput{
   453  			Path:   "/index",
   454  			Object: f2,
   455  		})
   456  		t.AssertNil(err)
   457  
   458  		// Schema asserts.
   459  		// fmt.Println(oai.String())
   460  		t.Assert(len(oai.Components.Schemas.Map()), 5)
   461  		t.Assert(len(oai.Paths), 1)
   462  		t.Assert(len(oai.Paths["/index"].Put.RequestBody.Value.Content["application/json"].Schema.Value.Properties.Map()), 1)
   463  		t.Assert(len(oai.Paths["/index"].Put.RequestBody.Value.Content["application/json"].Schema.Value.Properties.Get(`Request`).Value.Properties.Map()), 2)
   464  		t.Assert(len(oai.Paths["/index"].Post.RequestBody.Value.Content["application/json"].Schema.Value.Properties.Map()), 1)
   465  		t.Assert(len(oai.Paths["/index"].Post.RequestBody.Value.Content["application/json"].Schema.Value.Properties.Get(`Request`).Value.Properties.Map()), 4)
   466  	})
   467  }
   468  
   469  func TestOpenApiV3_CommonResponse(t *testing.T) {
   470  	type CommonResponse struct {
   471  		Code    int         `json:"code"    description:"Error code"`
   472  		Message string      `json:"message" description:"Error message"`
   473  		Data    interface{} `json:"data"    description:"Result data for certain request according API definition"`
   474  	}
   475  
   476  	type Req struct {
   477  		gmeta.Meta `method:"GET"`
   478  		Product    string `json:"product" in:"query" v:"required" description:"Unique product key"`
   479  		Name       string `json:"name"    in:"query"  v:"required" description:"Instance name"`
   480  	}
   481  	type Res struct {
   482  		Product      string `json:"product"      v:"required" description:"Unique product key"`
   483  		TemplateName string `json:"templateName" v:"required" description:"Workflow template name"`
   484  		Version      string `json:"version"      v:"required" description:"Workflow template version"`
   485  		TxID         string `json:"txID"         v:"required" description:"Transaction ID for creating instance"`
   486  		Globals      string `json:"globals"                   description:"Globals"`
   487  	}
   488  
   489  	f := func(ctx context.Context, req *Req) (res *Res, err error) {
   490  		return
   491  	}
   492  
   493  	gtest.C(t, func(t *gtest.T) {
   494  		var (
   495  			err error
   496  			oai = goai.New()
   497  		)
   498  
   499  		oai.Config.CommonResponse = CommonResponse{}
   500  		oai.Config.CommonResponseDataField = `Data`
   501  
   502  		err = oai.Add(goai.AddInput{
   503  			Path:   "/index",
   504  			Object: f,
   505  		})
   506  		t.AssertNil(err)
   507  
   508  		//g.Dump(oai.Paths["/index"].Get.Responses["200"].Value.Content["application/json"].Schema.Value.Properties.Map())
   509  		// Schema asserts.
   510  		t.Assert(len(oai.Components.Schemas.Map()), 3)
   511  		t.Assert(len(oai.Paths), 1)
   512  		t.Assert(len(oai.Paths["/index"].Get.Responses["200"].Value.Content["application/json"].Schema.Value.Properties.Map()), 3)
   513  		t.Assert(
   514  			oai.Paths["/index"].Get.Responses["200"].Value.Content["application/json"].Schema.Value.Properties.Get("data").Value.Description,
   515  			`Result data for certain request according API definition`,
   516  		)
   517  	})
   518  }
   519  
   520  func TestOpenApiV3_CommonResponse_WithoutDataField_Setting(t *testing.T) {
   521  	type CommonResponse struct {
   522  		Code    int         `json:"code"    description:"Error code"`
   523  		Message string      `json:"message" description:"Error message"`
   524  		Data    interface{} `json:"data"    description:"Result data for certain request according API definition"`
   525  	}
   526  
   527  	type Req struct {
   528  		gmeta.Meta `method:"GET"`
   529  		Product    string `json:"product" in:"query" v:"required" description:"Unique product key"`
   530  		Name       string `json:"name"    in:"query"  v:"required" description:"Instance name"`
   531  	}
   532  	type Res struct {
   533  		Product      string `json:"product"      v:"required" description:"Unique product key"`
   534  		TemplateName string `json:"templateName" v:"required" description:"Workflow template name"`
   535  		Version      string `json:"version"      v:"required" description:"Workflow template version"`
   536  		TxID         string `json:"txID"         v:"required" description:"Transaction ID for creating instance"`
   537  		Globals      string `json:"globals"                   description:"Globals"`
   538  	}
   539  
   540  	f := func(ctx context.Context, req *Req) (res *Res, err error) {
   541  		return
   542  	}
   543  
   544  	gtest.C(t, func(t *gtest.T) {
   545  		var (
   546  			err error
   547  			oai = goai.New()
   548  		)
   549  
   550  		oai.Config.CommonResponse = CommonResponse{}
   551  
   552  		err = oai.Add(goai.AddInput{
   553  			Path:   "/index",
   554  			Object: f,
   555  		})
   556  		t.AssertNil(err)
   557  		// Schema asserts.
   558  		fmt.Println(oai.String())
   559  		t.Assert(len(oai.Components.Schemas.Map()), 3)
   560  		t.Assert(len(oai.Paths), 1)
   561  		t.Assert(len(oai.Paths["/index"].Get.Responses["200"].Value.Content["application/json"].Schema.Value.Properties.Map()), 8)
   562  	})
   563  }
   564  
   565  func TestOpenApiV3_CommonResponse_EmptyResponse(t *testing.T) {
   566  	type CommonResponse struct {
   567  		Code    int         `json:"code"    description:"Error code"`
   568  		Message string      `json:"message" description:"Error message"`
   569  		Data    interface{} `json:"data"    description:"Result data for certain request according API definition"`
   570  	}
   571  
   572  	type Req struct {
   573  		gmeta.Meta `method:"PUT"`
   574  		Product    string `json:"product" v:"required" description:"Unique product key"`
   575  		Name       string `json:"name"    v:"required" description:"Instance name"`
   576  	}
   577  	type Res struct{}
   578  
   579  	f := func(ctx context.Context, req *Req) (res *Res, err error) {
   580  		return
   581  	}
   582  
   583  	gtest.C(t, func(t *gtest.T) {
   584  		var (
   585  			err error
   586  			oai = goai.New()
   587  		)
   588  
   589  		oai.Config.CommonResponse = CommonResponse{}
   590  		oai.Config.CommonResponseDataField = `Data`
   591  
   592  		err = oai.Add(goai.AddInput{
   593  			Path:   "/index",
   594  			Object: f,
   595  		})
   596  		t.AssertNil(err)
   597  		// Schema asserts.
   598  		// fmt.Println(oai.String())
   599  		t.Assert(len(oai.Components.Schemas.Map()), 3)
   600  		t.Assert(len(oai.Paths), 1)
   601  		t.Assert(oai.Paths["/index"].Put.RequestBody.Value.Content["application/json"].Schema.Ref, `github.com.gogf.gf.v2.net.goai_test.Req`)
   602  		t.Assert(len(oai.Paths["/index"].Put.Responses["200"].Value.Content["application/json"].Schema.Value.Properties.Map()), 3)
   603  	})
   604  }
   605  
   606  func TestOpenApiV3_CommonResponse_SubDataField(t *testing.T) {
   607  	type CommonResError struct {
   608  		Code    string `description:"错误码"`
   609  		Message string `description:"错误描述"`
   610  	}
   611  
   612  	type CommonResResponse struct {
   613  		RequestId string          `description:"RequestId"`
   614  		Error     *CommonResError `json:",omitempty" description:"执行错误信息"`
   615  	}
   616  
   617  	type CommonRes struct {
   618  		Response CommonResResponse
   619  	}
   620  
   621  	type Req struct {
   622  		gmeta.Meta `method:"GET"`
   623  		Product    string `json:"product" in:"query" v:"required" description:"Unique product key"`
   624  		Name       string `json:"name"    in:"query"  v:"required" description:"Instance name"`
   625  	}
   626  
   627  	type Res struct {
   628  		Product      string `json:"product"      v:"required" description:"Unique product key"`
   629  		TemplateName string `json:"templateName" v:"required" description:"Workflow template name"`
   630  		Version      string `json:"version"      v:"required" description:"Workflow template version"`
   631  		TxID         string `json:"txID"         v:"required" description:"Transaction ID for creating instance"`
   632  		Globals      string `json:"globals"                   description:"Globals"`
   633  	}
   634  
   635  	f := func(ctx context.Context, req *Req) (res *Res, err error) {
   636  		return
   637  	}
   638  
   639  	gtest.C(t, func(t *gtest.T) {
   640  		var (
   641  			err error
   642  			oai = goai.New()
   643  		)
   644  
   645  		oai.Config.CommonResponse = CommonRes{}
   646  		oai.Config.CommonResponseDataField = `Response.`
   647  
   648  		err = oai.Add(goai.AddInput{
   649  			Path:   "/index",
   650  			Object: f,
   651  		})
   652  		t.AssertNil(err)
   653  		// Schema asserts.
   654  		// fmt.Println(oai.String())
   655  		t.Assert(len(oai.Components.Schemas.Map()), 4)
   656  		t.Assert(len(oai.Paths), 1)
   657  		t.Assert(len(oai.Paths["/index"].Get.Responses["200"].Value.Content["application/json"].Schema.Value.Properties.Map()), 1)
   658  		t.Assert(len(oai.Paths["/index"].Get.Responses["200"].Value.Content["application/json"].Schema.Value.Properties.Get(`Response`).Value.Properties.Map()), 7)
   659  	})
   660  }
   661  
   662  func TestOpenApiV3_ShortTags(t *testing.T) {
   663  	type CommonReq struct {
   664  		AppId      int64  `json:"appId" v:"required" in:"path" dc:"应用Id" sm:"应用Id Summary"`
   665  		ResourceId string `json:"resourceId" in:"query" dc:"资源Id" sm:"资源Id Summary"`
   666  	}
   667  	type SetSpecInfo struct {
   668  		StorageType string   `v:"required|in:CLOUD_PREMIUM,CLOUD_SSD,CLOUD_HSSD" dc:"StorageType"`
   669  		Shards      int32    `dc:"shards 分片数" sm:"Shards Summary"`
   670  		Params      []string `dc:"默认参数(json 串-ClickHouseParams)" sm:"Params Summary"`
   671  	}
   672  	type CreateResourceReq struct {
   673  		CommonReq
   674  		gmeta.Meta `path:"/CreateResourceReq" method:"POST" tags:"default" sm:"CreateResourceReq sum" dc:"CreateResourceReq des"`
   675  		Name       string                  `dc:"实例名称"`
   676  		Product    string                  `dc:"业务类型"`
   677  		Region     string                  `v:"required" dc:"区域"`
   678  		SetMap     map[string]*SetSpecInfo `v:"required" dc:"配置Map"`
   679  		SetSlice   []SetSpecInfo           `v:"required" dc:"配置Slice"`
   680  	}
   681  
   682  	type CreateResourceRes struct {
   683  		gmeta.Meta `dc:"Demo Response Struct"`
   684  		FlowId     int64 `dc:"创建实例流程id"`
   685  	}
   686  
   687  	f := func(ctx context.Context, req *CreateResourceReq) (res *CreateResourceRes, err error) {
   688  		return
   689  	}
   690  
   691  	gtest.C(t, func(t *gtest.T) {
   692  		var (
   693  			err error
   694  			oai = goai.New()
   695  		)
   696  		err = oai.Add(goai.AddInput{
   697  			Path:   "/test1/{appId}",
   698  			Method: http.MethodPut,
   699  			Object: f,
   700  		})
   701  		t.AssertNil(err)
   702  
   703  		err = oai.Add(goai.AddInput{
   704  			Path:   "/test1/{appId}",
   705  			Method: http.MethodPost,
   706  			Object: f,
   707  		})
   708  		t.AssertNil(err)
   709  		// fmt.Println(oai.String())
   710  		// Schema asserts.
   711  		t.Assert(len(oai.Components.Schemas.Map()), 3)
   712  		t.Assert(oai.Paths[`/test1/{appId}`].Summary, ``)
   713  		t.Assert(oai.Paths[`/test1/{appId}`].Description, ``)
   714  		t.Assert(oai.Paths[`/test1/{appId}`].Put.Summary, `CreateResourceReq sum`)
   715  		t.Assert(oai.Paths[`/test1/{appId}`].Put.Description, `CreateResourceReq des`)
   716  		t.Assert(oai.Paths[`/test1/{appId}`].Put.Parameters[1].Value.Schema.Value.Description, `资源Id`)
   717  		t.Assert(oai.Components.Schemas.Get(`github.com.gogf.gf.v2.net.goai_test.CreateResourceReq`).Value.Properties.Get(`Name`).Value.Description, `实例名称`)
   718  	})
   719  }
   720  
   721  func TestOpenApiV3_HtmlResponse(t *testing.T) {
   722  	type Req struct {
   723  		g.Meta `path:"/test" method:"get" summary:"展示内容详情页面" tags:"内容"`
   724  		Id     uint `json:"id" v:"min:1#请选择查看的内容" dc:"内容id"`
   725  	}
   726  	type Res struct {
   727  		g.Meta `mime:"text/html" type:"string" example:"<html/>"`
   728  	}
   729  
   730  	f := func(ctx context.Context, req *Req) (res *Res, err error) {
   731  		return
   732  	}
   733  
   734  	gtest.C(t, func(t *gtest.T) {
   735  		var (
   736  			err error
   737  			oai = goai.New()
   738  		)
   739  		err = oai.Add(goai.AddInput{
   740  			Path:   "/test",
   741  			Method: http.MethodGet,
   742  			Object: f,
   743  		})
   744  		t.AssertNil(err)
   745  
   746  		// fmt.Println(oai.String())
   747  		t.Assert(oai.Components.Schemas.Get(`github.com.gogf.gf.v2.net.goai_test.Res`).Value.Type, goai.TypeString)
   748  	})
   749  }
   750  
   751  func TestOpenApiV3_HtmlResponseWithCommonResponse(t *testing.T) {
   752  	type CommonResError struct {
   753  		Code    string `description:"错误码"`
   754  		Message string `description:"错误描述"`
   755  	}
   756  
   757  	type CommonResResponse struct {
   758  		RequestId string          `description:"RequestId"`
   759  		Error     *CommonResError `json:",omitempty" description:"执行错误信息"`
   760  	}
   761  
   762  	type CommonRes struct {
   763  		Response CommonResResponse
   764  	}
   765  
   766  	type Req struct {
   767  		g.Meta `path:"/test" method:"get" summary:"展示内容详情页面" tags:"内容"`
   768  		Id     uint `json:"id" v:"min:1#请选择查看的内容" dc:"内容id"`
   769  	}
   770  	type Res struct {
   771  		g.Meta `mime:"text/html" type:"string" example:"<html/>"`
   772  	}
   773  
   774  	f := func(ctx context.Context, req *Req) (res *Res, err error) {
   775  		return
   776  	}
   777  
   778  	gtest.C(t, func(t *gtest.T) {
   779  		var (
   780  			err error
   781  			oai = goai.New()
   782  		)
   783  		oai.Config.CommonResponse = CommonRes{}
   784  		oai.Config.CommonResponseDataField = `Response.`
   785  
   786  		err = oai.Add(goai.AddInput{
   787  			Path:   "/test",
   788  			Method: http.MethodGet,
   789  			Object: f,
   790  		})
   791  		t.AssertNil(err)
   792  
   793  		// fmt.Println(oai.String())
   794  		t.Assert(oai.Components.Schemas.Get(`github.com.gogf.gf.v2.net.goai_test.Res`).Value.Type, goai.TypeString)
   795  	})
   796  }
   797  
   798  func Test_Required_In_Schema(t *testing.T) {
   799  	type CommonReq struct {
   800  		AppId      int64  `json:"appId" v:"required" in:"cookie" description:"应用Id"`
   801  		ResourceId string `json:"resourceId" in:"query" description:"资源Id"`
   802  	}
   803  	type SetSpecInfo struct {
   804  		StorageType string   `v:"required|in:CLOUD_PREMIUM,CLOUD_SSD,CLOUD_HSSD" description:"StorageType"`
   805  		Shards      int32    `description:"shards 分片数"`
   806  		Params      []string `description:"默认参数(json 串-ClickHouseParams)"`
   807  	}
   808  	type CreateResourceReq struct {
   809  		CommonReq
   810  		gmeta.Meta `path:"/CreateResourceReq" method:"POST" tags:"default"`
   811  		Name       string                  `description:"实例名称"`
   812  		Product    string                  `description:"业务类型"`
   813  		Region     string                  `v:"required|min:1" description:"区域"`
   814  		SetMap     map[string]*SetSpecInfo `v:"required|min:1" description:"配置Map"`
   815  		SetSlice   []SetSpecInfo           `v:"required|min:1" description:"配置Slice"`
   816  	}
   817  
   818  	gtest.C(t, func(t *gtest.T) {
   819  		var (
   820  			err error
   821  			oai = goai.New()
   822  			req = new(CreateResourceReq)
   823  		)
   824  		err = oai.Add(goai.AddInput{
   825  			Object: req,
   826  		})
   827  		t.AssertNil(err)
   828  		var (
   829  			schemaKey1 = `github.com.gogf.gf.v2.net.goai_test.CreateResourceReq`
   830  			schemaKey2 = `github.com.gogf.gf.v2.net.goai_test.SetSpecInfo`
   831  		)
   832  		t.Assert(oai.Components.Schemas.Map()[schemaKey1].Value.Required, g.Slice{
   833  			"appId",
   834  			"Region",
   835  			"SetMap",
   836  			"SetSlice",
   837  		})
   838  		t.Assert(oai.Components.Schemas.Map()[schemaKey2].Value.Required, g.Slice{
   839  			"StorageType",
   840  		})
   841  		t.Assert(oai.Components.Schemas.Map()[schemaKey2].Value.Properties.Map()["StorageType"].Value.Enum, g.Slice{
   842  			"CLOUD_PREMIUM",
   843  			"CLOUD_SSD",
   844  			"CLOUD_HSSD",
   845  		})
   846  	})
   847  }
   848  
   849  func Test_Properties_In_Sequence(t *testing.T) {
   850  	type ResourceCreateReq struct {
   851  		g.Meta           `path:"/resource" tags:"OSS Resource" method:"put" x-sort:"1" summary:"创建实例(发货)"`
   852  		AppId            uint64 `v:"required" dc:"应用Id"`
   853  		Uin              string `v:"required" dc:"主用户账号,该资源隶属于的账号"`
   854  		CreateUin        string `v:"required" dc:"创建实例的用户账号"`
   855  		Product          string `v:"required" dc:"业务类型" eg:"tdach"`
   856  		Region           string `v:"required" dc:"地域" eg:"ap-guangzhou"`
   857  		Zone             string `v:"required" dc:"区域" eg:"ap-guangzhou-1"`
   858  		Tenant           string `v:"required" dc:"业务自定义数据,透传到底层"`
   859  		VpcId            string `dc:"业务Vpc Id, TCS场景下非必须"`
   860  		SubnetId         string `dc:"业务Vpc子网Id"`
   861  		Name             string `dc:"自定义实例名称,默认和ResourceId一致"`
   862  		ClusterPreset    string `dc:"业务自定义Cluster定义,透传到底层"`
   863  		Engine           string `dc:"引擎名称,例如:TxLightning"`
   864  		Version          string `dc:"引擎版本,例如:10.3.213 (兼容ClickHouse 21.3.12)"`
   865  		SkipUpdateStatus bool   `dc:"是否跳过状态更新,继续保持creating" ed:"http://goframe.org"`
   866  	}
   867  	gtest.C(t, func(t *gtest.T) {
   868  		var (
   869  			err error
   870  			oai = goai.New()
   871  			req = new(ResourceCreateReq)
   872  		)
   873  		err = oai.Add(goai.AddInput{
   874  			Object: req,
   875  		})
   876  		t.AssertNil(err)
   877  		fmt.Println(oai)
   878  	})
   879  }
   880  
   881  func TestOpenApiV3_Ignore_Parameter(t *testing.T) {
   882  	type CommonResponse struct {
   883  		Code    int         `json:"code"    description:"Error code"`
   884  		Message string      `json:"message" description:"Error message"`
   885  		Data    interface{} `json:"data"    description:"Result data for certain request according API definition"`
   886  	}
   887  	type ProductSearchReq struct {
   888  		gmeta.Meta `path:"/test" method:"get"`
   889  		Product    string `json:"-" in:"query" v:"required|max:5" description:"Unique product key"`
   890  		Name       string `json:"name"    in:"query"  v:"required" description:"Instance name"`
   891  	}
   892  	type ProductSearchRes struct {
   893  		ID           int64  `json:"-"                         description:"Product ID"`
   894  		Product      string `json:"product"      v:"required" description:"Unique product key"`
   895  		TemplateName string `json:"templateName" v:"required" description:"Workflow template name"`
   896  		Version      string `json:"version"      v:"required" description:"Workflow template version"`
   897  		TxID         string `json:"txID"         v:"required" description:"Transaction ID for creating instance"`
   898  		Globals      string `json:"globals"                   description:"Globals"`
   899  	}
   900  
   901  	f := func(ctx context.Context, req *ProductSearchReq) (res *ProductSearchRes, err error) {
   902  		return
   903  	}
   904  
   905  	gtest.C(t, func(t *gtest.T) {
   906  		var (
   907  			err error
   908  			oai = goai.New()
   909  		)
   910  
   911  		oai.Config.CommonResponse = CommonResponse{}
   912  
   913  		err = oai.Add(goai.AddInput{
   914  			Object: f,
   915  		})
   916  		t.AssertNil(err)
   917  		// Schema asserts.
   918  		// fmt.Println(oai.String())
   919  		t.Assert(len(oai.Components.Schemas.Map()), 3)
   920  		t.Assert(len(oai.Paths), 1)
   921  		t.Assert(len(oai.Paths["/test"].Get.Responses["200"].Value.Content["application/json"].Schema.Value.Properties.Map()), 8)
   922  	})
   923  }
   924  
   925  func Test_EnumOfSchemaItems(t *testing.T) {
   926  	type CreateResourceReq struct {
   927  		gmeta.Meta `path:"/CreateResourceReq" method:"POST"`
   928  		Members    []string `v:"required|in:a,b,c"`
   929  	}
   930  
   931  	gtest.C(t, func(t *gtest.T) {
   932  		var (
   933  			err error
   934  			oai = goai.New()
   935  			req = new(CreateResourceReq)
   936  		)
   937  		err = oai.Add(goai.AddInput{
   938  			Object: req,
   939  		})
   940  		t.AssertNil(err)
   941  
   942  		t.Assert(
   943  			oai.Components.Schemas.Get(`github.com.gogf.gf.v2.net.goai_test.CreateResourceReq`).Value.
   944  				Properties.Get(`Members`).Value.
   945  				Items.Value.Enum,
   946  			g.Slice{"a", "b", "c"},
   947  		)
   948  	})
   949  }
   950  
   951  func Test_AliasNameOfAttribute(t *testing.T) {
   952  	type CreateResourceReq struct {
   953  		gmeta.Meta `path:"/CreateResourceReq" method:"POST"`
   954  		Name       string `p:"n"`
   955  		Age        string `json:"a"`
   956  	}
   957  
   958  	gtest.C(t, func(t *gtest.T) {
   959  		var (
   960  			err error
   961  			oai = goai.New()
   962  			req = new(CreateResourceReq)
   963  		)
   964  		err = oai.Add(goai.AddInput{
   965  			Object: req,
   966  		})
   967  		t.AssertNil(err)
   968  
   969  		t.Assert(
   970  			oai.Components.Schemas.Get(`github.com.gogf.gf.v2.net.goai_test.CreateResourceReq`).Value.
   971  				Properties.Get(`Name`), nil,
   972  		)
   973  		t.Assert(
   974  			oai.Components.Schemas.Get(`github.com.gogf.gf.v2.net.goai_test.CreateResourceReq`).Value.
   975  				Properties.Get(`Age`), nil,
   976  		)
   977  		t.AssertNE(
   978  			oai.Components.Schemas.Get(`github.com.gogf.gf.v2.net.goai_test.CreateResourceReq`).Value.
   979  				Properties.Get(`n`), nil,
   980  		)
   981  		t.AssertNE(
   982  			oai.Components.Schemas.Get(`github.com.gogf.gf.v2.net.goai_test.CreateResourceReq`).Value.
   983  				Properties.Get(`a`), nil,
   984  		)
   985  	})
   986  }
   987  
   988  func Test_EmbeddedStructAttribute(t *testing.T) {
   989  	type CreateResourceReq struct {
   990  		gmeta.Meta `path:"/CreateResourceReq" method:"POST"`
   991  		Name       string `dc:"This is name."`
   992  		Embedded   struct {
   993  			Age uint `dc:"This is embedded age."`
   994  		}
   995  	}
   996  
   997  	gtest.C(t, func(t *gtest.T) {
   998  		var (
   999  			err error
  1000  			oai = goai.New()
  1001  			req = new(CreateResourceReq)
  1002  		)
  1003  		err = oai.Add(goai.AddInput{
  1004  			Object: req,
  1005  		})
  1006  		t.AssertNil(err)
  1007  
  1008  		b, err := json.Marshal(oai)
  1009  		t.AssertNil(err)
  1010  		t.Assert(b, `{"openapi":"3.0.0","components":{"schemas":{"github.com.gogf.gf.v2.net.goai_test.CreateResourceReq":{"properties":{"Name":{"description":"This is name.","format":"string","properties":{},"type":"string"},"Embedded":{"properties":{"Age":{"description":"This is embedded age.","format":"uint","properties":{},"type":"integer"}},"type":"object"}},"type":"object"}}},"info":{"title":"","version":""},"paths":null}`)
  1011  	})
  1012  }
  1013  
  1014  func Test_NameFromJsonTag(t *testing.T) {
  1015  	// POST
  1016  	gtest.C(t, func(t *gtest.T) {
  1017  		type CreateReq struct {
  1018  			gmeta.Meta `path:"/CreateReq" method:"POST"`
  1019  			Name       string `json:"nick_name, omitempty"`
  1020  		}
  1021  
  1022  		var (
  1023  			err error
  1024  			oai = goai.New()
  1025  			req = new(CreateReq)
  1026  		)
  1027  		err = oai.Add(goai.AddInput{
  1028  			Object: req,
  1029  		})
  1030  		t.AssertNil(err)
  1031  
  1032  		b, err := json.Marshal(oai)
  1033  		t.AssertNil(err)
  1034  		t.Assert(b, `{"openapi":"3.0.0","components":{"schemas":{"github.com.gogf.gf.v2.net.goai_test.CreateReq":{"properties":{"nick_name":{"format":"string","properties":{},"type":"string"}},"type":"object"}}},"info":{"title":"","version":""},"paths":null}`)
  1035  	})
  1036  	// GET
  1037  	gtest.C(t, func(t *gtest.T) {
  1038  		type CreateReq struct {
  1039  			gmeta.Meta `path:"/CreateReq" method:"GET"`
  1040  			Name       string `json:"nick_name, omitempty" in:"header"`
  1041  		}
  1042  		var (
  1043  			err error
  1044  			oai = goai.New()
  1045  			req = new(CreateReq)
  1046  		)
  1047  		err = oai.Add(goai.AddInput{
  1048  			Object: req,
  1049  		})
  1050  		t.AssertNil(err)
  1051  
  1052  		b, err := json.Marshal(oai)
  1053  		t.AssertNil(err)
  1054  		fmt.Println(string(b))
  1055  		t.Assert(b, `{"openapi":"3.0.0","components":{"schemas":{"github.com.gogf.gf.v2.net.goai_test.CreateReq":{"properties":{"nick_name":{"format":"string","properties":{},"type":"string"}},"type":"object"}}},"info":{"title":"","version":""},"paths":null}`)
  1056  	})
  1057  }
  1058  
  1059  func TestOpenApiV3_PathSecurity(t *testing.T) {
  1060  	type CommonResponse struct {
  1061  		Code    int         `json:"code"    description:"Error code"`
  1062  		Message string      `json:"message" description:"Error message"`
  1063  		Data    interface{} `json:"data"    description:"Result data for certain request according API definition"`
  1064  	}
  1065  
  1066  	type Req struct {
  1067  		gmeta.Meta `method:"PUT" security:"apiKey"` // 这里的apiKey要和openApi定义的key一致
  1068  		Product    string                           `json:"product" v:"required" description:"Unique product key"`
  1069  		Name       string                           `json:"name"    v:"required" description:"Instance name"`
  1070  	}
  1071  	type Res struct{}
  1072  
  1073  	f := func(ctx context.Context, req *Req) (res *Res, err error) {
  1074  		return
  1075  	}
  1076  
  1077  	gtest.C(t, func(t *gtest.T) {
  1078  		var (
  1079  			err error
  1080  			oai = goai.New()
  1081  		)
  1082  
  1083  		oai.Config.CommonResponse = CommonResponse{}
  1084  		oai.Components = goai.Components{
  1085  			SecuritySchemes: goai.SecuritySchemes{
  1086  				"apiKey": goai.SecuritySchemeRef{
  1087  					Ref: "",
  1088  					Value: &goai.SecurityScheme{
  1089  						// 此处type是openApi的规定,详见 https://swagger.io/docs/specification/authentication/api-keys/
  1090  						Type: "apiKey",
  1091  						In:   "header",
  1092  						Name: "X-API-KEY",
  1093  					},
  1094  				},
  1095  			},
  1096  		}
  1097  		err = oai.Add(goai.AddInput{
  1098  			Path:   "/index",
  1099  			Object: f,
  1100  		})
  1101  		t.AssertNil(err)
  1102  		// Schema asserts.
  1103  		fmt.Println(oai.String())
  1104  		t.Assert(len(oai.Components.Schemas.Map()), 3)
  1105  		t.Assert(len(oai.Components.SecuritySchemes), 1)
  1106  		t.Assert(oai.Components.SecuritySchemes["apiKey"].Value.Type, "apiKey")
  1107  		t.Assert(len(oai.Paths), 1)
  1108  		t.Assert(len(oai.Paths["/index"].Put.Responses["200"].Value.Content["application/json"].Schema.Value.Properties.Map()), 3)
  1109  	})
  1110  }
  1111  
  1112  func Test_EmptyJsonNameWithOmitEmpty(t *testing.T) {
  1113  	type CreateResourceReq struct {
  1114  		gmeta.Meta `path:"/CreateResourceReq" method:"POST" tags:"default"`
  1115  		Name       string `description:"实例名称" json:",omitempty"`
  1116  		Product    string `description:"业务类型" json:",omitempty"`
  1117  	}
  1118  
  1119  	gtest.C(t, func(t *gtest.T) {
  1120  		var (
  1121  			err error
  1122  			oai = goai.New()
  1123  			req = new(CreateResourceReq)
  1124  		)
  1125  		err = oai.Add(goai.AddInput{
  1126  			Object: req,
  1127  		})
  1128  		t.AssertNil(err)
  1129  		var reqKey = "github.com.gogf.gf.v2.net.goai_test.CreateResourceReq"
  1130  		t.AssertNE(oai.Components.Schemas.Get(reqKey).Value.Properties.Get("Name"), nil)
  1131  		t.AssertNE(oai.Components.Schemas.Get(reqKey).Value.Properties.Get("Product"), nil)
  1132  		t.Assert(oai.Components.Schemas.Get(reqKey).Value.Properties.Get("None"), nil)
  1133  	})
  1134  }
  1135  
  1136  func Test_Enums(t *testing.T) {
  1137  	type Status string
  1138  	const (
  1139  		StatusA Status = "a"
  1140  		StatusB Status = "b"
  1141  	)
  1142  	type Req struct {
  1143  		gmeta.Meta `path:"/CreateResourceReq" method:"POST" tags:"default"`
  1144  		Name       string    `dc:"实例名称" json:",omitempty"`
  1145  		Status1    Status    `dc:"状态1" json:",omitempty"`
  1146  		Status2    *Status   `dc:"状态2" json:",omitempty"`
  1147  		Status3    []Status  `dc:"状态2" json:",omitempty"`
  1148  		Status4    []*Status `dc:"状态2" json:",omitempty"`
  1149  	}
  1150  
  1151  	gtest.C(t, func(t *gtest.T) {
  1152  		var (
  1153  			err error
  1154  			oai = goai.New()
  1155  			req = new(Req)
  1156  		)
  1157  		err = gtag.SetGlobalEnums(gjson.MustEncodeString(g.Map{
  1158  			"github.com/wangyougui/gf/v2/net/goai_test.Status": []interface{}{StatusA, StatusB},
  1159  		}))
  1160  		t.AssertNil(err)
  1161  
  1162  		err = oai.Add(goai.AddInput{
  1163  			Object: req,
  1164  		})
  1165  		t.AssertNil(err)
  1166  		var reqKey = "github.com.gogf.gf.v2.net.goai_test.Req"
  1167  		t.AssertNE(oai.Components.Schemas.Get(reqKey).Value.Properties.Get("Name"), nil)
  1168  		t.Assert(oai.Components.Schemas.Get(reqKey).Value.Properties.Get("Status1").Value.Enum, g.Slice{"a", "b"})
  1169  		t.Assert(oai.Components.Schemas.Get(reqKey).Value.Properties.Get("Status2").Value.Enum, g.Slice{"a", "b"})
  1170  		t.Assert(oai.Components.Schemas.Get(reqKey).Value.Properties.Get("Status3").Value.Items.Value.Enum, g.Slice{"a", "b"})
  1171  		t.Assert(oai.Components.Schemas.Get(reqKey).Value.Properties.Get("Status4").Value.Items.Value.Enum, g.Slice{"a", "b"})
  1172  	})
  1173  }
  1174  
  1175  func Test_XExtension(t *testing.T) {
  1176  	type GetListReq struct {
  1177  		g.Meta `path:"/user" tags:"User" method:"get" x-group:"User/Info" summary:"Get user list with basic info."`
  1178  		Page   int `dc:"Page number" d:"1" x-sort:"1"`
  1179  		Size   int `dc:"Size for per page." d:"10" x-sort:"2"`
  1180  	}
  1181  	gtest.C(t, func(t *gtest.T) {
  1182  		var (
  1183  			err error
  1184  			oai = goai.New()
  1185  			req = new(GetListReq)
  1186  		)
  1187  		err = oai.Add(goai.AddInput{
  1188  			Object: req,
  1189  		})
  1190  		t.AssertNil(err)
  1191  		t.Assert(oai.String(), `{"openapi":"3.0.0","components":{"schemas":{"github.com.gogf.gf.v2.net.goai_test.GetListReq":{"properties":{"Page":{"default":1,"description":"Page number","format":"int","properties":{},"type":"integer","x-sort":"1"},"Size":{"default":10,"description":"Size for per page.","format":"int","properties":{},"type":"integer","x-sort":"2"}},"type":"object","x-group":"User/Info"}}},"info":{"title":"","version":""},"paths":null}`)
  1192  	})
  1193  }