Skip to content

Commit

Permalink
Merge e7a4435 into cde0e46
Browse files Browse the repository at this point in the history
  • Loading branch information
AsterDY committed May 25, 2023
2 parents cde0e46 + e7a4435 commit b0d47b2
Show file tree
Hide file tree
Showing 8 changed files with 797 additions and 3 deletions.
1 change: 1 addition & 0 deletions go.mod
Expand Up @@ -8,6 +8,7 @@ require (
github.com/bytedance/mockey v1.2.0
github.com/choleraehyq/pid v0.0.16
github.com/cloudwego/configmanager v0.1.1
github.com/cloudwego/dynamicgo v0.1.0
github.com/cloudwego/fastpb v0.0.4
github.com/cloudwego/frugal v0.1.6
github.com/cloudwego/netpoll v0.3.2
Expand Down
49 changes: 47 additions & 2 deletions go.sum

Large diffs are not rendered by default.

23 changes: 23 additions & 0 deletions pkg/generic/reflect_test/idl/base.thrift
@@ -0,0 +1,23 @@
namespace py base
namespace go base
namespace java com.bytedance.thrift.base

struct TrafficEnv {
1: bool Open = false,
2: string Env = "",
}

struct Base {
1: string LogID = "",
2: string Caller = "",
3: string Addr = "",
4: string Client = "",
5: optional TrafficEnv TrafficEnv,
6: optional map<string, string> Extra,
}

struct BaseResp {
1: string StatusMessage = "",
2: i32 StatusCode = 0,
3: optional map<string, string> Extra,
}
49 changes: 49 additions & 0 deletions pkg/generic/reflect_test/idl/example.thrift
@@ -0,0 +1,49 @@
include "base.thrift"
include "self_ref.thrift"
namespace go kitex.test.server

enum FOO {
A = 1;
}

struct InnerBase {
255: base.Base Base,
}

struct MockElem {
1: string Bar
}

struct ExampleReq {
1: required string Msg = "Hello",
2: FOO Foo,
3: list<MockElem> TestList,
4: optional map<string, MockElem> TestMap,
5: list<string> StrList,
6: list<i64> I64List = [1, 2, 3],
7: bool B,
255: base.Base Base,
}
struct ExampleResp {
1: required string Msg,
2: string required_field
255: base.BaseResp BaseResp,
}
exception Exception {
1: i32 code
2: string msg
}

struct A {
1: A self
2: self_ref.A a
}

service ExampleService {
ExampleReq ExampleMethod(1: ExampleReq req)throws(1: Exception err),
ExampleResp ExampleMethod2(1: ExampleReq req)throws(1: Exception err),
A Foo(1: A req)
string Ping(1: string msg)
oneway void Oneway(1: string msg)
void Void(1: string msg)
}
6 changes: 6 additions & 0 deletions pkg/generic/reflect_test/idl/self_ref.thrift
@@ -0,0 +1,6 @@
namespace go kitex.test.server

struct A {
1: A self
2: string extra
}
198 changes: 198 additions & 0 deletions pkg/generic/reflect_test/map_test.go
@@ -0,0 +1,198 @@
/**
* Copyright 2023 ByteDance Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

package test

import (
"context"
"errors"
"math/rand"
"net"
"strconv"
"testing"
"time"

"github.com/cloudwego/kitex/client"
"github.com/cloudwego/kitex/client/callopt"
"github.com/cloudwego/kitex/client/genericclient"
"github.com/cloudwego/kitex/internal/test"
"github.com/cloudwego/kitex/pkg/generic"
"github.com/cloudwego/kitex/server"
"github.com/cloudwego/kitex/server/genericserver"
)

var mcli genericclient.Client

func TestThriftMapExample(t *testing.T) {
testThriftMapExample(t)
}

func BenchmarkThriftMapExample(b *testing.B) {
for i := 0; i < b.N; i++ {
testThriftMapExample(b)
}
}

func testThriftMapExample(t testing.TB) {
log_id := strconv.Itoa(rand.Int())

req := makeExampleReqMap(true, reqMsg, log_id)

out, err := mcli.GenericCall(context.Background(), method, req, callopt.WithRPCTimeout(100*time.Second))
test.Assert(t, err == nil, err)
resp, ok := out.(map[string]interface{})
test.Assert(t, ok)

msg, ok := resp["Msg"].(string)
if !ok || msg != respMsg {
t.Fail()
}
require_field, ok := resp["required_field"].(string)
if !ok || require_field != reqMsg {
t.Fail()
}
logid, ok := resp["BaseResp"].(map[string]interface{})["StatusMessage"]
if !ok || log_id != logid {
t.Fail()
}
}

func initThriftMapClient(addr, idl string) genericclient.Client {
p, err := generic.NewThriftFileProvider(idl)
if err != nil {
panic(err)
}
g, err := generic.MapThriftGeneric(p)
if err != nil {
panic(err)
}
cli := newGenericClient("destServiceName", g, addr)
if err != nil {
panic(err)
}
return cli
}

func newGenericClient(destService string, g generic.Generic, targetIPPort string) genericclient.Client {
var opts []client.Option
opts = append(opts, client.WithHostPorts(targetIPPort))
genericCli, _ := genericclient.NewClient(destService, g, opts...)
return genericCli
}

func initThriftMapServer(address, idl string, handler generic.Service) server.Server {
addr, _ := net.ResolveTCPAddr("tcp", address)
p, err := generic.NewThriftFileProvider(idl)
if err != nil {
panic(err)
}
g, err := generic.MapThriftGeneric(p)
if err != nil {
panic(err)
}
svr := newGenericServer(g, addr, handler)
if err != nil {
panic(err)
}
time.Sleep(500 * time.Millisecond)
return svr
}

func newGenericServer(g generic.Generic, addr net.Addr, handler generic.Service) server.Server {
var opts []server.Option
opts = append(opts, server.WithServiceAddr(addr))
svr := genericserver.NewServer(handler, g, opts...)
go func() {
err := svr.Run()
if err != nil {
panic(err)
}
}()
return svr
}

type exampeServerImpl struct{}

// GenericCall ...
func (g *exampeServerImpl) GenericCall(ctx context.Context, method string, request interface{}) (response interface{}, err error) {
buf := request.(map[string]interface{})

required_field := ""
logid := ""
if b, ok := buf["B"].(bool); ok && b {
if base, ok := buf["Base"].(map[string]interface{}); !ok {
return nil, errors.New("empty base field")
} else {
logid, _ = base["LogID"].(string)
}
if testmap, ok := buf["TestMap"].(map[interface{}]interface{}); !ok {
return nil, errors.New("empty TestMap")
} else if a, ok := testmap["a"].(map[string]interface{}); !ok {
return nil, errors.New("key 'a' not found")
} else {
required_field, _ = a["Bar"].(string)
}
}

return makeExampleRespMap(respMsg, required_field, logid)
}

func makeExampleRespMap(msg, require_field, logid string) (map[string]interface{}, error) {
return map[string]interface{}{
"Msg": msg,
"required_field": require_field,
"BaseResp": map[string]interface{}{
"StatusMessage": logid,
},
}, nil
}

func makeExampleReqMap(B bool, A, logid string) map[string]interface{} {
list := make([]interface{}, SampleListSize+1)
list[0] = map[string]interface{}{
"Bar": A,
}
for i := 1; i < len(list); i++ {
list[i] = map[string]interface{}{
"Bar": A,
}
}
m := make(map[string]interface{}, SampleListSize+1)
m["a"] = map[string]interface{}{
"Bar": A,
}
for i := 1; i < len(list); i++ {
m[strconv.Itoa(i)] = map[string]interface{}{
"Bar": A,
}
}
return map[string]interface{}{
"Msg": "Hello",
"Foo": int32(1),
"TestList": list,
"TestMap": m,
"I64List": []interface{}{
int64(1), int64(2), int64(3),
},
"B": B,
"Base": map[string]interface{}{
"LogID": logid,
"Caller": "d.e.f",
"Addr": "127.0.0.1",
"Client": "dynamicgo",
},
}
}

0 comments on commit b0d47b2

Please sign in to comment.