github.com/cloudwego/kitex@v0.9.0/pkg/generic/reflect_test/map_test.go (about)

     1  /**
     2   * Copyright 2023 ByteDance Inc.
     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 test
    18  
    19  import (
    20  	"context"
    21  	"errors"
    22  	"math/rand"
    23  	"net"
    24  	"strconv"
    25  	"testing"
    26  	"time"
    27  
    28  	"github.com/cloudwego/kitex/client"
    29  	"github.com/cloudwego/kitex/client/callopt"
    30  	"github.com/cloudwego/kitex/client/genericclient"
    31  	"github.com/cloudwego/kitex/internal/test"
    32  	"github.com/cloudwego/kitex/pkg/generic"
    33  	"github.com/cloudwego/kitex/server"
    34  	"github.com/cloudwego/kitex/server/genericserver"
    35  )
    36  
    37  var mcli genericclient.Client
    38  
    39  func TestThriftMapExample(t *testing.T) {
    40  	testThriftMapExample(t)
    41  }
    42  
    43  func BenchmarkThriftMapExample(b *testing.B) {
    44  	for i := 0; i < b.N; i++ {
    45  		testThriftMapExample(b)
    46  	}
    47  }
    48  
    49  func testThriftMapExample(t testing.TB) {
    50  	log_id := strconv.Itoa(rand.Int())
    51  
    52  	req := makeExampleReqMap(true, reqMsg, log_id)
    53  
    54  	out, err := mcli.GenericCall(context.Background(), method, req, callopt.WithRPCTimeout(100*time.Second))
    55  	test.Assert(t, err == nil, err)
    56  	resp, ok := out.(map[string]interface{})
    57  	test.Assert(t, ok)
    58  
    59  	msg, ok := resp["Msg"].(string)
    60  	if !ok || msg != respMsg {
    61  		t.Fail()
    62  	}
    63  	require_field, ok := resp["required_field"].(string)
    64  	if !ok || require_field != reqMsg {
    65  		t.Fail()
    66  	}
    67  	logid, ok := resp["BaseResp"].(map[string]interface{})["StatusMessage"]
    68  	if !ok || log_id != logid {
    69  		t.Fail()
    70  	}
    71  }
    72  
    73  func initThriftMapClient(addr, idl string) genericclient.Client {
    74  	p, err := generic.NewThriftFileProvider(idl)
    75  	if err != nil {
    76  		panic(err)
    77  	}
    78  	g, err := generic.MapThriftGeneric(p)
    79  	if err != nil {
    80  		panic(err)
    81  	}
    82  	cli := newGenericClient("destServiceName", g, addr)
    83  	if err != nil {
    84  		panic(err)
    85  	}
    86  	return cli
    87  }
    88  
    89  func newGenericClient(destService string, g generic.Generic, targetIPPort string) genericclient.Client {
    90  	var opts []client.Option
    91  	opts = append(opts, client.WithHostPorts(targetIPPort))
    92  	genericCli, _ := genericclient.NewClient(destService, g, opts...)
    93  	return genericCli
    94  }
    95  
    96  func initThriftMapServer(address, idl string, handler generic.Service) server.Server {
    97  	addr, _ := net.ResolveTCPAddr("tcp", address)
    98  	p, err := generic.NewThriftFileProvider(idl)
    99  	if err != nil {
   100  		panic(err)
   101  	}
   102  	g, err := generic.MapThriftGeneric(p)
   103  	if err != nil {
   104  		panic(err)
   105  	}
   106  	svr := newGenericServer(g, addr, handler)
   107  	return svr
   108  }
   109  
   110  func newGenericServer(g generic.Generic, addr net.Addr, handler generic.Service) server.Server {
   111  	var opts []server.Option
   112  	opts = append(opts, server.WithServiceAddr(addr), server.WithExitWaitTime(time.Microsecond*10))
   113  	svr := genericserver.NewServer(handler, g, opts...)
   114  	go func() {
   115  		err := svr.Run()
   116  		if err != nil {
   117  			panic(err)
   118  		}
   119  	}()
   120  	test.WaitServerStart(addr.String())
   121  	return svr
   122  }
   123  
   124  type exampeServerImpl struct{}
   125  
   126  // GenericCall ...
   127  func (g *exampeServerImpl) GenericCall(ctx context.Context, method string, request interface{}) (response interface{}, err error) {
   128  	buf := request.(map[string]interface{})
   129  
   130  	required_field := ""
   131  	logid := ""
   132  	if b, ok := buf["B"].(bool); ok && b {
   133  		if base, ok := buf["Base"].(map[string]interface{}); !ok {
   134  			return nil, errors.New("empty base field")
   135  		} else {
   136  			logid, _ = base["LogID"].(string)
   137  		}
   138  		if testmap, ok := buf["TestMap"].(map[interface{}]interface{}); !ok {
   139  			return nil, errors.New("empty TestMap")
   140  		} else if a, ok := testmap["a"].(map[string]interface{}); !ok {
   141  			return nil, errors.New("key 'a' not found")
   142  		} else {
   143  			required_field, _ = a["Bar"].(string)
   144  		}
   145  	}
   146  
   147  	return makeExampleRespMap(respMsg, required_field, logid)
   148  }
   149  
   150  func makeExampleRespMap(msg, require_field, logid string) (map[string]interface{}, error) {
   151  	return map[string]interface{}{
   152  		"Msg":            msg,
   153  		"required_field": require_field,
   154  		"BaseResp": map[string]interface{}{
   155  			"StatusMessage": logid,
   156  		},
   157  	}, nil
   158  }
   159  
   160  func makeExampleReqMap(B bool, A, logid string) map[string]interface{} {
   161  	list := make([]interface{}, SampleListSize+1)
   162  	list[0] = map[string]interface{}{
   163  		"Bar": A,
   164  	}
   165  	for i := 1; i < len(list); i++ {
   166  		list[i] = map[string]interface{}{
   167  			"Bar": A,
   168  		}
   169  	}
   170  	m := make(map[string]interface{}, SampleListSize+1)
   171  	m["a"] = map[string]interface{}{
   172  		"Bar": A,
   173  	}
   174  	for i := 1; i < len(list); i++ {
   175  		m[strconv.Itoa(i)] = map[string]interface{}{
   176  			"Bar": A,
   177  		}
   178  	}
   179  	return map[string]interface{}{
   180  		"Msg":      "Hello",
   181  		"Foo":      int32(1),
   182  		"TestList": list,
   183  		"TestMap":  m,
   184  		"I64List": []interface{}{
   185  			int64(1), int64(2), int64(3),
   186  		},
   187  		"B": B,
   188  		"Base": map[string]interface{}{
   189  			"LogID":  logid,
   190  			"Caller": "d.e.f",
   191  			"Addr":   "127.0.0.1",
   192  			"Client": "dynamicgo",
   193  		},
   194  	}
   195  }