trpc.group/trpc-go/trpc-cmdline@v1.0.9/util/apidocs/swagger_test.go (about)

     1  // Tencent is pleased to support the open source community by making tRPC available.
     2  //
     3  // Copyright (C) 2023 THL A29 Limited, a Tencent company.
     4  // All rights reserved.
     5  //
     6  // If you have downloaded a copy of the tRPC source code from Tencent,
     7  // please note that tRPC source code is licensed under the  Apache 2.0 License,
     8  // A copy of the Apache 2.0 License is included in this file.
     9  
    10  package apidocs
    11  
    12  import (
    13  	"encoding/json"
    14  	"fmt"
    15  	"os"
    16  
    17  	"reflect"
    18  	"testing"
    19  
    20  	"github.com/agiledragon/gomonkey"
    21  	"github.com/jhump/protoreflect/desc"
    22  	"github.com/stretchr/testify/require"
    23  
    24  	"trpc.group/trpc-go/trpc-cmdline/descriptor"
    25  	"trpc.group/trpc-go/trpc-cmdline/params"
    26  	"trpc.group/trpc-go/trpc-cmdline/parser"
    27  	"trpc.group/trpc-go/trpc-cmdline/util/paths"
    28  )
    29  
    30  func TestNewSwagger(t *testing.T) {
    31  	type args struct {
    32  		fd     *descriptor.FileDescriptor
    33  		option *params.Option
    34  	}
    35  	tests := []struct {
    36  		name              string
    37  		args              args
    38  		want              *SwaggerJSON
    39  		wantErr           bool
    40  		genSwaggerInfoErr error
    41  	}{
    42  		{
    43  			name: "case1-genSwaggerInfo_error",
    44  			args: args{
    45  				fd: &descriptor.FileDescriptor{
    46  					FD: &descriptor.ProtoFileDescriptor{
    47  						FD: &desc.FileDescriptor{},
    48  					},
    49  				},
    50  				option: &params.Option{},
    51  			},
    52  			want:              nil,
    53  			wantErr:           true,
    54  			genSwaggerInfoErr: fmt.Errorf("error"),
    55  		},
    56  		{
    57  			name: "case1-fd_nil",
    58  			args: args{
    59  				fd:     &descriptor.FileDescriptor{},
    60  				option: &params.Option{},
    61  			},
    62  			want:    nil,
    63  			wantErr: true,
    64  		},
    65  		{
    66  			name: "case2-success",
    67  			args: args{
    68  				fd: &descriptor.FileDescriptor{
    69  					FD: &descriptor.ProtoFileDescriptor{
    70  						FD: &desc.FileDescriptor{},
    71  					},
    72  				},
    73  				option: &params.Option{},
    74  			},
    75  			want: &SwaggerJSON{
    76  				Swagger:  "2.0",
    77  				Info:     InfoStruct{},
    78  				Consumes: []string{"application/json"},
    79  				Produces: []string{"application/json"},
    80  				Paths: Paths{
    81  					Elements: make(map[string]Methods),
    82  					Rank:     make(map[string]int),
    83  				},
    84  				Definitions: make(map[string]ModelStruct),
    85  			},
    86  			wantErr: false,
    87  		},
    88  	}
    89  	for _, tt := range tests {
    90  		t.Run(tt.name, func(t *testing.T) {
    91  			p := gomonkey.ApplyFunc(
    92  				NewInfo,
    93  				func(fd *descriptor.FileDescriptor) (InfoStruct, error) {
    94  					return InfoStruct{}, tt.genSwaggerInfoErr
    95  				},
    96  			)
    97  
    98  			p.ApplyFunc(
    99  				NewDefinitions,
   100  				func(options *params.Option, fds ...descriptor.Desc) *Definitions {
   101  					return &Definitions{
   102  						models: make(map[string]ModelStruct),
   103  					}
   104  				},
   105  			)
   106  
   107  			p.ApplyFunc(
   108  				NewPaths,
   109  				func(fd *descriptor.FileDescriptor, option *params.Option, defs *Definitions) (Paths, error) {
   110  					return Paths{
   111  						Elements: make(map[string]Methods),
   112  						Rank:     make(map[string]int),
   113  					}, nil
   114  				},
   115  			)
   116  
   117  			defer p.Reset()
   118  
   119  			got, err := NewSwagger(tt.args.fd, tt.args.option)
   120  			if (err != nil) != tt.wantErr {
   121  				t.Errorf("NewSwagger() error = %v, wantErr %v", err, tt.wantErr)
   122  				return
   123  			}
   124  			if !reflect.DeepEqual(got, tt.want) {
   125  				t.Errorf("NewSwagger() got = %v, want %v", got, tt.want)
   126  			}
   127  		})
   128  	}
   129  }
   130  
   131  func TestNewSwagger_with_file(t *testing.T) {
   132  	option := &params.Option{
   133  		Protodirs: append([]string{
   134  			".",
   135  			"../../install",
   136  			"../../install/protos",
   137  		}, paths.ExpandTRPCSearch("../../install")...),
   138  		Protofile:           "testcase/hello.proto",
   139  		ProtofileAbs:        "testcase/hello.proto",
   140  		SwaggerOptJSONParam: true,
   141  		KeepOrigRPCName:     true,
   142  	}
   143  
   144  	fd, err := parser.ParseProtoFile(
   145  		option.Protofile,
   146  		option.Protodirs,
   147  		parser.WithAliasOn(option.AliasOn),
   148  		parser.WithLanguage(option.Language),
   149  		parser.WithRPCOnly(option.RPCOnly),
   150  	)
   151  	if err != nil {
   152  		t.Logf("cannot parse proto file, option: %+v, err: %+v", option, err)
   153  		t.FailNow()
   154  	}
   155  
   156  	swagger, err := NewSwagger(fd, option)
   157  	require.NoError(t, err)
   158  
   159  	gotByte, err := json.MarshalIndent(swagger, "", " ")
   160  	require.NoError(t, err)
   161  
   162  	wantByte, err := os.ReadFile("testcase/swagger.json")
   163  	require.NoError(t, err)
   164  
   165  	require.Equal(t, string(wantByte), string(gotByte))
   166  }
   167  
   168  func TestNewSwagger_OrderByPBName_with_file(t *testing.T) {
   169  	option := &params.Option{
   170  		Protodirs: append([]string{
   171  			".",
   172  			"../../install",
   173  			"../../install/protos",
   174  		}, paths.ExpandTRPCSearch("../../install")...),
   175  		Protofile:           "testcase/hello.proto",
   176  		ProtofileAbs:        "testcase/hello.proto",
   177  		SwaggerOptJSONParam: true,
   178  		OrderByPBName:       true,
   179  		KeepOrigRPCName:     true,
   180  	}
   181  
   182  	fd, err := parser.ParseProtoFile(
   183  		option.Protofile,
   184  		option.Protodirs,
   185  		parser.WithAliasOn(option.AliasOn),
   186  		parser.WithLanguage(option.Language),
   187  		parser.WithRPCOnly(option.RPCOnly),
   188  	)
   189  	if err != nil {
   190  		t.Logf("cannot parse proto file, option: %+v, err: %+v", option, err)
   191  		t.FailNow()
   192  	}
   193  
   194  	swagger, err := NewSwagger(fd, option)
   195  	require.NoError(t, err)
   196  
   197  	gotByte, err := json.MarshalIndent(swagger, "", " ")
   198  	require.NoError(t, err)
   199  
   200  	wantByte, err := os.ReadFile("testcase/swagger_order_by_pbname.json")
   201  	require.NoError(t, err)
   202  
   203  	require.Equal(t, string(wantByte), string(gotByte))
   204  }
   205  
   206  func TestNewSwagger_Unmarshal_file(t *testing.T) {
   207  	option := &params.Option{
   208  		Protodirs: append([]string{
   209  			".",
   210  			"../../install",
   211  			"../../install/protos",
   212  		}, paths.ExpandTRPCSearch("../../install")...),
   213  		Protofile:           "testcase/hello.proto",
   214  		ProtofileAbs:        "testcase/hello.proto",
   215  		SwaggerOptJSONParam: true,
   216  		OrderByPBName:       true,
   217  		KeepOrigRPCName:     true,
   218  	}
   219  
   220  	fd, err := parser.ParseProtoFile(
   221  		option.Protofile,
   222  		option.Protodirs,
   223  		parser.WithAliasOn(option.AliasOn),
   224  		parser.WithLanguage(option.Language),
   225  		parser.WithRPCOnly(option.RPCOnly),
   226  	)
   227  	if err != nil {
   228  		t.Logf("cannot parse proto file, option: %+v, err: %+v", option, err)
   229  		t.FailNow()
   230  	}
   231  
   232  	gotSwagger, err := NewSwagger(fd, option)
   233  	require.NoError(t, err)
   234  
   235  	wantByte, err := os.ReadFile("testcase/swagger_order_by_pbname.json")
   236  	require.NoError(t, err)
   237  
   238  	var wantSwagger = &SwaggerJSON{}
   239  	err = json.Unmarshal(wantByte, wantSwagger)
   240  	require.NoError(t, err)
   241  
   242  	require.Equal(t, wantSwagger, gotSwagger)
   243  }