github.com/cloudwego/dynamicgo@v0.2.6-0.20240519101509-707f41b6b834/thrift/binary_test.go (about)

     1  /**
     2   * Copyright 2023 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  	"fmt"
    22  	"io/ioutil"
    23  	"os"
    24  	"runtime"
    25  	"runtime/debug"
    26  	"strings"
    27  	"testing"
    28  	"time"
    29  
    30  	"github.com/stretchr/testify/require"
    31  )
    32  
    33  var (
    34  	debugAsyncGC = os.Getenv("SONIC_NO_ASYNC_GC") == ""
    35  )
    36  
    37  func TestMain(m *testing.M) {
    38  	go func() {
    39  		if !debugAsyncGC {
    40  			return
    41  		}
    42  		println("Begin GC looping...")
    43  		for {
    44  			runtime.GC()
    45  			debug.FreeOSMemory()
    46  		}
    47  	}()
    48  	time.Sleep(time.Millisecond)
    49  	m.Run()
    50  }
    51  
    52  func getExampleDesc() *TypeDescriptor {
    53  	svc, err := NewDescritorFromPath(context.Background(), "../testdata/idl/example.thrift")
    54  	if err != nil {
    55  		panic(err)
    56  	}
    57  	return svc.Functions()["ExampleMethod"].Request().Struct().FieldByKey("req").Type()
    58  }
    59  
    60  func getExampleData() []byte {
    61  	out, err := ioutil.ReadFile("../testdata/data/example.bin")
    62  	if err != nil {
    63  		panic(err)
    64  	}
    65  	return out
    66  }
    67  
    68  func TestBinaryProtocol_ReadAnyWithDesc(t *testing.T) {
    69  	p1, err := NewDescritorFromPath(context.Background(), "../testdata/idl/example3.thrift")
    70  	if err != nil {
    71  		panic(err)
    72  	}
    73  	exp3partial := p1.Functions()["PartialMethod"].Response().Struct().FieldById(0).Type()
    74  	data, err := ioutil.ReadFile("../testdata/data/example3.bin")
    75  	if err != nil {
    76  		panic(err)
    77  	}
    78  
    79  	p := NewBinaryProtocol(data)
    80  	v, err := p.ReadAnyWithDesc(exp3partial, false, false, false, true)
    81  	if err != nil {
    82  		panic(err)
    83  	}
    84  	fmt.Printf("%#v", v)
    85  	p = NewBinaryProtocolBuffer()
    86  	err = p.WriteAnyWithDesc(exp3partial, v, true, true, true)
    87  	if err != nil {
    88  		panic(err)
    89  	}
    90  	fmt.Printf("%x", p.RawBuf())
    91  	v, err = p.ReadAnyWithDesc(exp3partial, false, false, false, true)
    92  	if err != nil {
    93  		panic(err)
    94  	}
    95  	fmt.Printf("%#v", v)
    96  }
    97  
    98  func TestBinaryProtocol_WriteAny_ReadAny(t *testing.T) {
    99  	type args struct {
   100  		val         interface{}
   101  		sliceAsSet  bool
   102  		strAsBinary bool
   103  		byteAsInt8  bool
   104  	}
   105  	tests := []struct {
   106  		name    string
   107  		args    args
   108  		wantErr bool
   109  		want    interface{}
   110  	}{
   111  		{"bool", args{true, false, false, false}, false, true},
   112  		{"byte", args{byte(1), false, false, false}, false, byte(1)},
   113  		{"byte", args{byte(1), false, false, true}, false, int8(1)},
   114  		{"i16", args{int16(1), false, false, false}, false, int16(1)},
   115  		{"i32", args{int32(1), false, false, false}, false, int32(1)},
   116  		{"i64", args{int64(1), false, false, false}, false, int64(1)},
   117  		{"int", args{1, false, false, false}, false, int64(1)},
   118  		{"f32", args{float32(1.0), false, false, false}, false, float64(1.0)},
   119  		{"f64", args{1.0, false, false, false}, false, float64(1.0)},
   120  		{"string", args{"1", false, false, false}, false, "1"},
   121  		{"string2binary", args{"1", false, true, false}, false, []byte{'1'}},
   122  		{"binary2string", args{[]byte{1}, false, false, false}, false, string("\x01")},
   123  		{"binary2binary", args{[]byte{1}, false, true, false}, false, []byte{1}},
   124  		{"list", args{[]interface{}{int32(1)}, false, false, false}, false, []interface{}{int32(1)}},
   125  		{"set", args{[]interface{}{int64(1)}, true, false, false}, false, []interface{}{int64(1)}},
   126  		{"int map", args{map[int]interface{}{1: byte(1)}, false, false, false}, false, map[int]interface{}{1: byte(1)}},
   127  		{"int map error", args{map[int64]interface{}{1: byte(1)}, false, false, true}, false, map[int]interface{}{1: int8(1)}},
   128  		{"int map empty", args{map[int64]interface{}{}, false, false, false}, true, nil},
   129  		{"string map", args{map[string]interface{}{"1": "1"}, false, false, true}, false, map[string]interface{}{"1": "1"}},
   130  		{"string map error", args{map[string]interface{}{"1": []int{1}}, false, false, true}, true, nil},
   131  		{"string map empty", args{map[string]interface{}{}, false, false, true}, true, nil},
   132  		{"any map", args{map[interface{}]interface{}{1.1: "1"}, false, false, false}, false, map[interface{}]interface{}{1.1: "1"}},
   133  		{"any map + key list", args{map[interface{}]interface{}{&[]interface{}{1}: "1"}, false, false, false}, false, map[interface{}]interface{}{&[]interface{}{int64(1)}: "1"}},
   134  		{"any map + val list", args{map[interface{}]interface{}{1.1: []interface{}{"1"}}, false, true, false}, false, map[interface{}]interface{}{1.1: []interface{}{[]byte{'1'}}}},
   135  		{"any map empty", args{map[interface{}]interface{}{}, false, false, false}, true, nil},
   136  		{"struct", args{map[FieldID]interface{}{FieldID(1): 1.1}, false, false, false}, false, map[FieldID]interface{}{FieldID(1): 1.1}},
   137  	}
   138  	for _, tt := range tests {
   139  		t.Run(tt.name, func(t *testing.T) {
   140  			println("case:", tt.name)
   141  			p := &BinaryProtocol{}
   142  			typ, err := p.WriteAny(tt.args.val, tt.args.sliceAsSet)
   143  			if (err != nil) != tt.wantErr {
   144  				t.Fatalf("BinaryProtocol.WriteAny() error = %v, wantErr %v", err, tt.wantErr)
   145  			}
   146  			fmt.Printf("buf:%+v\n", p.RawBuf())
   147  			got, err := p.ReadAny(typ, tt.args.strAsBinary, tt.args.byteAsInt8)
   148  			if (err != nil) != tt.wantErr {
   149  				t.Fatalf("BinaryProtocol.ReadAny() error = %v, wantErr %v", err, tt.wantErr)
   150  			}
   151  			fmt.Printf("got:%#v\n", got)
   152  			if strings.Contains(tt.name, "any map + key") {
   153  				em := tt.want.(map[interface{}]interface{})
   154  				gm := got.(map[interface{}]interface{})
   155  				require.Equal(t, len(em), len(gm))
   156  				var firstK, firstV interface{}
   157  				for k, v := range em {
   158  					firstK, firstV = k, v
   159  					break
   160  				}
   161  				var firstKgot, firstVgot interface{}
   162  				for k, v := range gm {
   163  					firstKgot, firstVgot = k, v
   164  					break
   165  				}
   166  				require.Equal(t, firstK, firstKgot)
   167  				require.Equal(t, firstV, firstVgot)
   168  			} else {
   169  				require.Equal(t, tt.want, got)
   170  			}
   171  		})
   172  	}
   173  }