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