github.com/cloudwego/kitex@v0.9.0/pkg/generic/thrift/read_test.go (about)

     1  /*
     2   * Copyright 2021 CloudWeGo Authors
     3   *
     4   * Licensed under the Apache License, Version 2.0 (the "License");
     5   * you may not use this file except in compliance with the License.
     6   * You may obtain a copy of the License at
     7   *
     8   *     http://www.apache.org/licenses/LICENSE-2.0
     9   *
    10   * Unless required by applicable law or agreed to in writing, software
    11   * distributed under the License is distributed on an "AS IS" BASIS,
    12   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    13   * See the License for the specific language governing permissions and
    14   * limitations under the License.
    15   */
    16  
    17  package thrift
    18  
    19  import (
    20  	"context"
    21  	"encoding/base64"
    22  	"errors"
    23  	"fmt"
    24  	"reflect"
    25  	"testing"
    26  
    27  	"github.com/apache/thrift/lib/go/thrift"
    28  	"github.com/jhump/protoreflect/desc/protoparse"
    29  
    30  	"github.com/cloudwego/kitex/internal/mocks"
    31  	"github.com/cloudwego/kitex/pkg/generic/descriptor"
    32  	"github.com/cloudwego/kitex/pkg/generic/proto"
    33  )
    34  
    35  var (
    36  	stringInput = "hello world"
    37  	binaryInput = []byte(stringInput)
    38  )
    39  
    40  func Test_nextReader(t *testing.T) {
    41  	type args struct {
    42  		tt  descriptor.Type
    43  		t   *descriptor.TypeDescriptor
    44  		opt *readerOption
    45  	}
    46  	tests := []struct {
    47  		name    string
    48  		args    args
    49  		want    reader
    50  		wantErr bool
    51  	}{
    52  		// TODO: Add test cases.
    53  		{"void", args{tt: descriptor.VOID, t: &descriptor.TypeDescriptor{Type: descriptor.VOID}, opt: &readerOption{}}, readVoid, false},
    54  	}
    55  	for _, tt := range tests {
    56  		t.Run(tt.name, func(t *testing.T) {
    57  			got, err := nextReader(tt.args.tt, tt.args.t, tt.args.opt)
    58  			if (err != nil) != tt.wantErr {
    59  				t.Errorf("nextReader() error = %v, wantErr %v", err, tt.wantErr)
    60  				return
    61  			}
    62  			if fmt.Sprintf("%p", got) != fmt.Sprintf("%p", tt.want) {
    63  				t.Errorf("nextReader() = %v, want %v", got, tt.want)
    64  			}
    65  		})
    66  	}
    67  }
    68  
    69  func Test_readVoid(t *testing.T) {
    70  	type args struct {
    71  		in  thrift.TProtocol
    72  		t   *descriptor.TypeDescriptor
    73  		opt *readerOption
    74  	}
    75  
    76  	mockTTransport := &mocks.MockThriftTTransport{}
    77  	tests := []struct {
    78  		name    string
    79  		args    args
    80  		want    interface{}
    81  		wantErr bool
    82  	}{
    83  		// TODO: Add test cases.
    84  		{"void", args{in: mockTTransport, t: &descriptor.TypeDescriptor{Type: descriptor.VOID}}, descriptor.Void{}, false},
    85  	}
    86  	for _, tt := range tests {
    87  		t.Run(tt.name, func(t *testing.T) {
    88  			got, err := readVoid(context.Background(), tt.args.in, tt.args.t, tt.args.opt)
    89  			if (err != nil) != tt.wantErr {
    90  				t.Errorf("readVoid() error = %v, wantErr %v", err, tt.wantErr)
    91  				return
    92  			}
    93  			if !reflect.DeepEqual(got, tt.want) {
    94  				t.Errorf("readVoid() = %v, want %v", got, tt.want)
    95  			}
    96  		})
    97  	}
    98  }
    99  
   100  func Test_readDouble(t *testing.T) {
   101  	type args struct {
   102  		in  thrift.TProtocol
   103  		t   *descriptor.TypeDescriptor
   104  		opt *readerOption
   105  	}
   106  	mockTTransport := &mocks.MockThriftTTransport{
   107  		ReadDoubleFunc: func() (value float64, err error) {
   108  			return 1.0, nil
   109  		},
   110  	}
   111  	tests := []struct {
   112  		name    string
   113  		args    args
   114  		want    interface{}
   115  		wantErr bool
   116  	}{
   117  		// TODO: Add test cases.
   118  		{"readDouble", args{in: mockTTransport, t: &descriptor.TypeDescriptor{Type: descriptor.DOUBLE}}, 1.0, false},
   119  	}
   120  	for _, tt := range tests {
   121  		t.Run(tt.name, func(t *testing.T) {
   122  			got, err := readDouble(context.Background(), tt.args.in, tt.args.t, tt.args.opt)
   123  			if (err != nil) != tt.wantErr {
   124  				t.Errorf("readDouble() error = %v, wantErr %v", err, tt.wantErr)
   125  				return
   126  			}
   127  			if !reflect.DeepEqual(got, tt.want) {
   128  				t.Errorf("readDouble() = %v, want %v", got, tt.want)
   129  			}
   130  		})
   131  	}
   132  }
   133  
   134  func Test_readBool(t *testing.T) {
   135  	type args struct {
   136  		in  thrift.TProtocol
   137  		t   *descriptor.TypeDescriptor
   138  		opt *readerOption
   139  	}
   140  	mockTTransport := &mocks.MockThriftTTransport{
   141  		ReadBoolFunc: func() (bool, error) { return true, nil },
   142  	}
   143  	tests := []struct {
   144  		name    string
   145  		args    args
   146  		want    interface{}
   147  		wantErr bool
   148  	}{
   149  		// TODO: Add test cases.
   150  		{"readBool", args{in: mockTTransport, t: &descriptor.TypeDescriptor{Type: descriptor.BOOL}}, true, false},
   151  	}
   152  	for _, tt := range tests {
   153  		t.Run(tt.name, func(t *testing.T) {
   154  			got, err := readBool(context.Background(), tt.args.in, tt.args.t, tt.args.opt)
   155  			if (err != nil) != tt.wantErr {
   156  				t.Errorf("readBool() error = %v, wantErr %v", err, tt.wantErr)
   157  				return
   158  			}
   159  			if !reflect.DeepEqual(got, tt.want) {
   160  				t.Errorf("readBool() = %v, want %v", got, tt.want)
   161  			}
   162  		})
   163  	}
   164  }
   165  
   166  func Test_readByte(t *testing.T) {
   167  	type args struct {
   168  		in  thrift.TProtocol
   169  		t   *descriptor.TypeDescriptor
   170  		opt *readerOption
   171  	}
   172  	mockTTransport := &mocks.MockThriftTTransport{
   173  		ReadByteFunc: func() (int8, error) {
   174  			return 1, nil
   175  		},
   176  	}
   177  	tests := []struct {
   178  		name    string
   179  		args    args
   180  		want    interface{}
   181  		wantErr bool
   182  	}{
   183  		// TODO: Add test cases.
   184  		{"readByte", args{in: mockTTransport, t: &descriptor.TypeDescriptor{Type: descriptor.BYTE}, opt: &readerOption{}}, int8(1), false},
   185  	}
   186  	for _, tt := range tests {
   187  		t.Run(tt.name, func(t *testing.T) {
   188  			got, err := readByte(context.Background(), tt.args.in, tt.args.t, tt.args.opt)
   189  			if (err != nil) != tt.wantErr {
   190  				t.Errorf("readByte() error = %v, wantErr %v", err, tt.wantErr)
   191  				return
   192  			}
   193  			if !reflect.DeepEqual(got, tt.want) {
   194  				t.Errorf("readByte() = %v, want %v", got, tt.want)
   195  			}
   196  		})
   197  	}
   198  }
   199  
   200  func Test_readInt16(t *testing.T) {
   201  	type args struct {
   202  		in  thrift.TProtocol
   203  		t   *descriptor.TypeDescriptor
   204  		opt *readerOption
   205  	}
   206  	mockTTransport := &mocks.MockThriftTTransport{
   207  		ReadI16Func: func() (int16, error) {
   208  			return 1, nil
   209  		},
   210  	}
   211  	tests := []struct {
   212  		name    string
   213  		args    args
   214  		want    interface{}
   215  		wantErr bool
   216  	}{
   217  		// TODO: Add test cases.
   218  		{"readInt16", args{in: mockTTransport, t: &descriptor.TypeDescriptor{Type: descriptor.I16}, opt: &readerOption{}}, int16(1), false},
   219  	}
   220  	for _, tt := range tests {
   221  		t.Run(tt.name, func(t *testing.T) {
   222  			got, err := readInt16(context.Background(), tt.args.in, tt.args.t, tt.args.opt)
   223  			if (err != nil) != tt.wantErr {
   224  				t.Errorf("readInt16() error = %v, wantErr %v", err, tt.wantErr)
   225  				return
   226  			}
   227  			if !reflect.DeepEqual(got, tt.want) {
   228  				t.Errorf("readInt16() = %v, want %v", got, tt.want)
   229  			}
   230  		})
   231  	}
   232  }
   233  
   234  func Test_readInt32(t *testing.T) {
   235  	type args struct {
   236  		in  thrift.TProtocol
   237  		t   *descriptor.TypeDescriptor
   238  		opt *readerOption
   239  	}
   240  
   241  	mockTTransport := &mocks.MockThriftTTransport{
   242  		ReadI32Func: func() (int32, error) {
   243  			return 1, nil
   244  		},
   245  	}
   246  	tests := []struct {
   247  		name    string
   248  		args    args
   249  		want    interface{}
   250  		wantErr bool
   251  	}{
   252  		// TODO: Add test cases.
   253  		{"readInt32", args{in: mockTTransport, t: &descriptor.TypeDescriptor{Type: descriptor.I32}}, int32(1), false},
   254  	}
   255  	for _, tt := range tests {
   256  		t.Run(tt.name, func(t *testing.T) {
   257  			got, err := readInt32(context.Background(), tt.args.in, tt.args.t, tt.args.opt)
   258  			if (err != nil) != tt.wantErr {
   259  				t.Errorf("readInt32() error = %v, wantErr %v", err, tt.wantErr)
   260  				return
   261  			}
   262  			if !reflect.DeepEqual(got, tt.want) {
   263  				t.Errorf("readInt32() = %v, want %v", got, tt.want)
   264  			}
   265  		})
   266  	}
   267  }
   268  
   269  func Test_readInt64(t *testing.T) {
   270  	type args struct {
   271  		in  thrift.TProtocol
   272  		t   *descriptor.TypeDescriptor
   273  		opt *readerOption
   274  	}
   275  	mockTTransport := &mocks.MockThriftTTransport{
   276  		ReadI64Func: func() (int64, error) {
   277  			return 1, nil
   278  		},
   279  	}
   280  	tests := []struct {
   281  		name    string
   282  		args    args
   283  		want    interface{}
   284  		wantErr bool
   285  	}{
   286  		// TODO: Add test cases.
   287  		{"readInt64", args{in: mockTTransport, t: &descriptor.TypeDescriptor{Type: descriptor.I64}}, int64(1), false},
   288  	}
   289  	for _, tt := range tests {
   290  		t.Run(tt.name, func(t *testing.T) {
   291  			got, err := readInt64(context.Background(), tt.args.in, tt.args.t, tt.args.opt)
   292  			if (err != nil) != tt.wantErr {
   293  				t.Errorf("readInt64() error = %v, wantErr %v", err, tt.wantErr)
   294  				return
   295  			}
   296  			if !reflect.DeepEqual(got, tt.want) {
   297  				t.Errorf("readInt64() = %v, want %v", got, tt.want)
   298  			}
   299  		})
   300  	}
   301  }
   302  
   303  func Test_readString(t *testing.T) {
   304  	type args struct {
   305  		in  thrift.TProtocol
   306  		t   *descriptor.TypeDescriptor
   307  		opt *readerOption
   308  	}
   309  	mockTTransport := &mocks.MockThriftTTransport{
   310  		ReadStringFunc: func() (string, error) {
   311  			return stringInput, nil
   312  		},
   313  		ReadBinaryFunc: func() ([]byte, error) {
   314  			return binaryInput, nil
   315  		},
   316  	}
   317  	tests := []struct {
   318  		name    string
   319  		args    args
   320  		want    interface{}
   321  		wantErr bool
   322  	}{
   323  		// TODO: Add test cases.
   324  		{"readString", args{in: mockTTransport, t: &descriptor.TypeDescriptor{Type: descriptor.STRING}}, stringInput, false},
   325  	}
   326  	for _, tt := range tests {
   327  		t.Run(tt.name, func(t *testing.T) {
   328  			got, err := readString(context.Background(), tt.args.in, tt.args.t, tt.args.opt)
   329  			if (err != nil) != tt.wantErr {
   330  				t.Errorf("readString() error = %v, wantErr %v", err, tt.wantErr)
   331  				return
   332  			}
   333  			if !reflect.DeepEqual(got, tt.want) {
   334  				t.Errorf("readString() = %v, want %v", got, tt.want)
   335  			}
   336  		})
   337  	}
   338  }
   339  
   340  func Test_readBinary64String(t *testing.T) {
   341  	type args struct {
   342  		in  thrift.TProtocol
   343  		t   *descriptor.TypeDescriptor
   344  		opt *readerOption
   345  	}
   346  	mockTTransport := &mocks.MockThriftTTransport{
   347  		ReadStringFunc: func() (string, error) {
   348  			return stringInput, nil
   349  		},
   350  		ReadBinaryFunc: func() ([]byte, error) {
   351  			return binaryInput, nil
   352  		},
   353  	}
   354  	tests := []struct {
   355  		name    string
   356  		args    args
   357  		want    interface{}
   358  		wantErr bool
   359  	}{
   360  		// TODO: Add test cases.
   361  		{"readBase64Binary", args{in: mockTTransport, t: &descriptor.TypeDescriptor{Name: "binary", Type: descriptor.STRING}}, base64.StdEncoding.EncodeToString(binaryInput), false}, // read base64 string from binary field
   362  	}
   363  	for _, tt := range tests {
   364  		t.Run(tt.name, func(t *testing.T) {
   365  			got, err := readBase64Binary(context.Background(), tt.args.in, tt.args.t, tt.args.opt)
   366  			if (err != nil) != tt.wantErr {
   367  				t.Errorf("readString() error = %v, wantErr %v", err, tt.wantErr)
   368  				return
   369  			}
   370  			if !reflect.DeepEqual(got, tt.want) {
   371  				t.Errorf("readString() = %v, want %v", got, tt.want)
   372  			}
   373  		})
   374  	}
   375  }
   376  
   377  func Test_readBinary(t *testing.T) {
   378  	type args struct {
   379  		in  thrift.TProtocol
   380  		t   *descriptor.TypeDescriptor
   381  		opt *readerOption
   382  	}
   383  	mockTTransport := &mocks.MockThriftTTransport{
   384  		ReadStringFunc: func() (string, error) {
   385  			return stringInput, nil
   386  		},
   387  		ReadBinaryFunc: func() ([]byte, error) {
   388  			return binaryInput, nil
   389  		},
   390  	}
   391  	tests := []struct {
   392  		name    string
   393  		args    args
   394  		want    interface{}
   395  		wantErr bool
   396  	}{
   397  		// TODO: Add test cases.
   398  		{"readBinary", args{in: mockTTransport, t: &descriptor.TypeDescriptor{Name: "binary", Type: descriptor.STRING}}, binaryInput, false}, // read base64 string from binary field
   399  	}
   400  	for _, tt := range tests {
   401  		t.Run(tt.name, func(t *testing.T) {
   402  			got, err := readBinary(context.Background(), tt.args.in, tt.args.t, tt.args.opt)
   403  			if (err != nil) != tt.wantErr {
   404  				t.Errorf("readString() error = %v, wantErr %v", err, tt.wantErr)
   405  				return
   406  			}
   407  			if !reflect.DeepEqual(got, tt.want) {
   408  				t.Errorf("readString() = %v, want %v", got, tt.want)
   409  			}
   410  		})
   411  	}
   412  }
   413  
   414  func Test_readList(t *testing.T) {
   415  	type args struct {
   416  		in  thrift.TProtocol
   417  		t   *descriptor.TypeDescriptor
   418  		opt *readerOption
   419  	}
   420  	mockTTransport := &mocks.MockThriftTTransport{
   421  		ReadListBeginFunc: func() (elemType thrift.TType, size int, err error) {
   422  			return thrift.STRING, 3, nil
   423  		},
   424  
   425  		ReadStringFunc: func() (string, error) {
   426  			return stringInput, nil
   427  		},
   428  	}
   429  	tests := []struct {
   430  		name    string
   431  		args    args
   432  		want    interface{}
   433  		wantErr bool
   434  	}{
   435  		// TODO: Add test cases.
   436  		{"readList", args{in: mockTTransport, t: &descriptor.TypeDescriptor{Type: descriptor.LIST, Elem: &descriptor.TypeDescriptor{Type: descriptor.STRING}}}, []interface{}{stringInput, stringInput, stringInput}, false},
   437  	}
   438  	for _, tt := range tests {
   439  		t.Run(tt.name, func(t *testing.T) {
   440  			got, err := readList(context.Background(), tt.args.in, tt.args.t, tt.args.opt)
   441  			if (err != nil) != tt.wantErr {
   442  				t.Errorf("readList() error = %v, wantErr %v", err, tt.wantErr)
   443  				return
   444  			}
   445  			if !reflect.DeepEqual(got, tt.want) {
   446  				t.Errorf("readList() = %v, want %v", got, tt.want)
   447  			}
   448  		})
   449  	}
   450  }
   451  
   452  func Test_readMap(t *testing.T) {
   453  	type args struct {
   454  		in  thrift.TProtocol
   455  		t   *descriptor.TypeDescriptor
   456  		opt *readerOption
   457  	}
   458  	count := 0
   459  	mockTTransport := &mocks.MockThriftTTransport{
   460  		ReadMapBeginFunc: func() (keyType, valueType thrift.TType, size int, err error) {
   461  			return thrift.STRING, thrift.STRING, 1, nil
   462  		},
   463  		ReadStringFunc: func() (string, error) {
   464  			defer func() { count++ }()
   465  			if count%2 == 0 {
   466  				return "hello", nil
   467  			}
   468  			return "world", nil
   469  		},
   470  	}
   471  	mockTTransportWithInt16Key := &mocks.MockThriftTTransport{
   472  		ReadMapBeginFunc: func() (keyType, valueType thrift.TType, size int, err error) {
   473  			return thrift.I16, thrift.BOOL, 1, nil
   474  		},
   475  		ReadI16Func: func() (int16, error) {
   476  			return 16, nil
   477  		},
   478  	}
   479  	tests := []struct {
   480  		name    string
   481  		args    args
   482  		want    interface{}
   483  		wantErr bool
   484  	}{
   485  		// TODO: Add test cases.
   486  		{
   487  			"readMap",
   488  			args{in: mockTTransport, t: &descriptor.TypeDescriptor{Type: descriptor.MAP, Key: &descriptor.TypeDescriptor{Type: descriptor.STRING}, Elem: &descriptor.TypeDescriptor{Type: descriptor.STRING}}, opt: &readerOption{}},
   489  			map[interface{}]interface{}{"hello": "world"},
   490  			false,
   491  		},
   492  		{
   493  			"readJsonMap",
   494  			args{in: mockTTransport, t: &descriptor.TypeDescriptor{Type: descriptor.MAP, Key: &descriptor.TypeDescriptor{Type: descriptor.STRING}, Elem: &descriptor.TypeDescriptor{Type: descriptor.STRING}}, opt: &readerOption{forJSON: true}},
   495  			map[string]interface{}{"hello": "world"},
   496  			false,
   497  		},
   498  		{
   499  			"readJsonMapWithInt16Key",
   500  			args{in: mockTTransportWithInt16Key, t: &descriptor.TypeDescriptor{Type: descriptor.MAP, Key: &descriptor.TypeDescriptor{Type: descriptor.I16}, Elem: &descriptor.TypeDescriptor{Type: descriptor.BOOL}}, opt: &readerOption{forJSON: true}},
   501  			map[string]interface{}{"16": false},
   502  			false,
   503  		},
   504  	}
   505  	for _, tt := range tests {
   506  		t.Run(tt.name, func(t *testing.T) {
   507  			got, err := readMap(context.Background(), tt.args.in, tt.args.t, tt.args.opt)
   508  			if (err != nil) != tt.wantErr {
   509  				t.Errorf("readMap() error = %v, wantErr %v", err, tt.wantErr)
   510  				return
   511  			}
   512  			if !reflect.DeepEqual(got, tt.want) {
   513  				t.Errorf("readMap() = %v, want %v", got, tt.want)
   514  			}
   515  		})
   516  	}
   517  }
   518  
   519  func Test_readStruct(t *testing.T) {
   520  	type args struct {
   521  		in  thrift.TProtocol
   522  		t   *descriptor.TypeDescriptor
   523  		opt *readerOption
   524  	}
   525  	read := false
   526  	mockTTransport := &mocks.MockThriftTTransport{
   527  		ReadStructBeginFunc: func() (name string, err error) {
   528  			return "Demo", nil
   529  		},
   530  		ReadFieldBeginFunc: func() (name string, typeID thrift.TType, id int16, err error) {
   531  			if !read {
   532  				read = true
   533  				return "", thrift.STRING, 1, nil
   534  			}
   535  			return "", thrift.STOP, 0, nil
   536  		},
   537  		ReadStringFunc: func() (string, error) {
   538  			return "world", nil
   539  		},
   540  	}
   541  	readError := false
   542  	mockTTransportError := &mocks.MockThriftTTransport{
   543  		ReadStructBeginFunc: func() (name string, err error) {
   544  			return "Demo", nil
   545  		},
   546  		ReadFieldBeginFunc: func() (name string, typeID thrift.TType, id int16, err error) {
   547  			if !readError {
   548  				readError = true
   549  				return "", thrift.LIST, 1, nil
   550  			}
   551  			return "", thrift.STOP, 0, nil
   552  		},
   553  		ReadListBeginFunc: func() (elemType thrift.TType, size int, err error) {
   554  			return thrift.STRING, 1, nil
   555  		},
   556  		ReadStringFunc: func() (string, error) {
   557  			return "123", errors.New("need STRING type, but got: I64")
   558  		},
   559  	}
   560  	tests := []struct {
   561  		name    string
   562  		args    args
   563  		want    interface{}
   564  		wantErr bool
   565  	}{
   566  		// TODO: Add test cases.
   567  		{
   568  			"readStruct",
   569  			args{in: mockTTransport, t: &descriptor.TypeDescriptor{
   570  				Type: descriptor.STRUCT,
   571  				Struct: &descriptor.StructDescriptor{
   572  					FieldsByID: map[int32]*descriptor.FieldDescriptor{
   573  						1: {Name: "hello", Type: &descriptor.TypeDescriptor{Type: descriptor.STRING}},
   574  					},
   575  				},
   576  			}},
   577  			map[string]interface{}{"hello": "world"},
   578  			false,
   579  		},
   580  		{
   581  			"readStructError",
   582  			args{in: mockTTransportError, t: &descriptor.TypeDescriptor{
   583  				Type: descriptor.STRUCT,
   584  				Struct: &descriptor.StructDescriptor{
   585  					FieldsByID: map[int32]*descriptor.FieldDescriptor{
   586  						1: {Name: "strList", Type: &descriptor.TypeDescriptor{Type: descriptor.LIST, Elem: &descriptor.TypeDescriptor{Type: descriptor.STRING}}},
   587  					},
   588  				},
   589  			}},
   590  			nil,
   591  			true,
   592  		},
   593  	}
   594  	for _, tt := range tests {
   595  		t.Run(tt.name, func(t *testing.T) {
   596  			got, err := readStruct(context.Background(), tt.args.in, tt.args.t, tt.args.opt)
   597  			if (err != nil) != tt.wantErr {
   598  				t.Errorf("readStruct() error = %v, wantErr %v", err, tt.wantErr)
   599  				return
   600  			}
   601  			if !reflect.DeepEqual(got, tt.want) {
   602  				t.Errorf("readStruct() = %v, want %v", got, tt.want)
   603  			}
   604  		})
   605  	}
   606  }
   607  
   608  func Test_readHTTPResponse(t *testing.T) {
   609  	type args struct {
   610  		in  thrift.TProtocol
   611  		t   *descriptor.TypeDescriptor
   612  		opt *readerOption
   613  	}
   614  	read := false
   615  	mockTTransport := &mocks.MockThriftTTransport{
   616  		ReadStructBeginFunc: func() (name string, err error) {
   617  			return "Demo", nil
   618  		},
   619  		ReadFieldBeginFunc: func() (name string, typeID thrift.TType, id int16, err error) {
   620  			if !read {
   621  				read = true
   622  				return "", thrift.STRING, 1, nil
   623  			}
   624  			return "", thrift.STOP, 0, nil
   625  		},
   626  		ReadStringFunc: func() (string, error) {
   627  			return "world", nil
   628  		},
   629  	}
   630  	resp := descriptor.NewHTTPResponse()
   631  	resp.Body = map[string]interface{}{"hello": "world"}
   632  	tests := []struct {
   633  		name    string
   634  		args    args
   635  		want    interface{}
   636  		wantErr bool
   637  	}{
   638  		// TODO: Add test cases.
   639  		{
   640  			"readHTTPResponse",
   641  			args{in: mockTTransport, t: &descriptor.TypeDescriptor{
   642  				Type: descriptor.STRUCT,
   643  				Struct: &descriptor.StructDescriptor{
   644  					FieldsByID: map[int32]*descriptor.FieldDescriptor{
   645  						1: {
   646  							Name:        "hello",
   647  							Type:        &descriptor.TypeDescriptor{Type: descriptor.STRING},
   648  							HTTPMapping: descriptor.DefaultNewMapping("hello"),
   649  						},
   650  					},
   651  				},
   652  			}},
   653  			resp,
   654  			false,
   655  		},
   656  	}
   657  	for _, tt := range tests {
   658  		t.Run(tt.name, func(t *testing.T) {
   659  			got, err := readHTTPResponse(context.Background(), tt.args.in, tt.args.t, tt.args.opt)
   660  			if (err != nil) != tt.wantErr {
   661  				t.Errorf("readHTTPResponse() error = %v, wantErr %v", err, tt.wantErr)
   662  				return
   663  			}
   664  			if !reflect.DeepEqual(got, tt.want) {
   665  				t.Errorf("readHTTPResponse() = %v, want %v", got, tt.want)
   666  			}
   667  		})
   668  	}
   669  }
   670  
   671  func Test_readHTTPResponseWithPbBody(t *testing.T) {
   672  	type args struct {
   673  		in  thrift.TProtocol
   674  		t   *descriptor.TypeDescriptor
   675  		opt *readerOption
   676  	}
   677  	read := false
   678  	mockTTransport := &mocks.MockThriftTTransport{
   679  		ReadStructBeginFunc: func() (name string, err error) {
   680  			return "BizResp", nil
   681  		},
   682  		ReadFieldBeginFunc: func() (name string, typeID thrift.TType, id int16, err error) {
   683  			if !read {
   684  				read = true
   685  				return "", thrift.STRING, 1, nil
   686  			}
   687  			return "", thrift.STOP, 0, nil
   688  		},
   689  		ReadStringFunc: func() (string, error) {
   690  			return "hello world", nil
   691  		},
   692  	}
   693  	desc, err := getRespPbDesc()
   694  	if err != nil {
   695  		t.Error(err)
   696  		return
   697  	}
   698  	tests := []struct {
   699  		name    string
   700  		args    args
   701  		want    map[int]interface{}
   702  		wantErr bool
   703  	}{
   704  		// TODO: Add test cases.
   705  		{
   706  			"readHTTPResponse",
   707  			args{in: mockTTransport, t: &descriptor.TypeDescriptor{
   708  				Type: descriptor.STRUCT,
   709  				Struct: &descriptor.StructDescriptor{
   710  					FieldsByID: map[int32]*descriptor.FieldDescriptor{
   711  						1: {
   712  							ID:          1,
   713  							Name:        "msg",
   714  							Type:        &descriptor.TypeDescriptor{Type: descriptor.STRING},
   715  							HTTPMapping: descriptor.DefaultNewMapping("msg"),
   716  						},
   717  					},
   718  				},
   719  			}, opt: &readerOption{pbDsc: desc}},
   720  			map[int]interface{}{
   721  				1: "hello world",
   722  			},
   723  			false,
   724  		},
   725  	}
   726  	for _, tt := range tests {
   727  		t.Run(tt.name, func(t *testing.T) {
   728  			got, err := readHTTPResponse(context.Background(), tt.args.in, tt.args.t, tt.args.opt)
   729  			if (err != nil) != tt.wantErr {
   730  				t.Errorf("readHTTPResponse() error = %v, wantErr %v", err, tt.wantErr)
   731  				return
   732  			}
   733  			respGot := got.(*descriptor.HTTPResponse)
   734  			if respGot.ContentType != descriptor.MIMEApplicationProtobuf {
   735  				t.Errorf("expected content type: %v, got: %v", descriptor.MIMEApplicationProtobuf, respGot.ContentType)
   736  			}
   737  			body := respGot.GeneralBody.(proto.Message)
   738  			for fieldID, expectedVal := range tt.want {
   739  				val, err := body.TryGetFieldByNumber(fieldID)
   740  				if err != nil {
   741  					t.Errorf("get by fieldID [%v] err: %v", fieldID, err)
   742  				}
   743  				if val != expectedVal {
   744  					t.Errorf("expected field value: %v, got: %v", expectedVal, val)
   745  				}
   746  			}
   747  		})
   748  	}
   749  }
   750  
   751  func getRespPbDesc() (proto.MessageDescriptor, error) {
   752  	path := "main.proto"
   753  	content := `
   754  	package kitex.test.server;
   755  
   756  	message BizResp {
   757  		optional string msg = 1;
   758  	}
   759  	`
   760  
   761  	var pbParser protoparse.Parser
   762  	pbParser.Accessor = protoparse.FileContentsFromMap(map[string]string{path: content})
   763  	fds, err := pbParser.ParseFiles(path)
   764  	if err != nil {
   765  		return nil, err
   766  	}
   767  
   768  	return fds[0].GetMessageTypes()[0], nil
   769  }