github.com/cloudwego/kitex@v0.9.0/pkg/generic/binary_test/generic_init.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 test ... 18 package test 19 20 import ( 21 "context" 22 "encoding/binary" 23 "errors" 24 "fmt" 25 "net" 26 "time" 27 28 "github.com/apache/thrift/lib/go/thrift" 29 30 "github.com/cloudwego/kitex/client" 31 "github.com/cloudwego/kitex/client/genericclient" 32 kt "github.com/cloudwego/kitex/internal/mocks/thrift" 33 "github.com/cloudwego/kitex/internal/test" 34 "github.com/cloudwego/kitex/pkg/generic" 35 "github.com/cloudwego/kitex/pkg/serviceinfo" 36 "github.com/cloudwego/kitex/pkg/utils" 37 "github.com/cloudwego/kitex/server" 38 "github.com/cloudwego/kitex/server/genericserver" 39 ) 40 41 var ( 42 reqMsg = "Hello Kitex" 43 respMsg = "Hi, I am Kitex" 44 errResp = "Test Error" 45 ) 46 47 func newGenericClient(destService string, g generic.Generic, targetIPPort string, opts ...client.Option) genericclient.Client { 48 opts = append(opts, client.WithHostPorts(targetIPPort)) 49 genericCli, _ := genericclient.NewClient(destService, g, opts...) 50 return genericCli 51 } 52 53 func newGenericServer(g generic.Generic, addr net.Addr, handler generic.Service) server.Server { 54 var opts []server.Option 55 opts = append(opts, server.WithServiceAddr(addr), server.WithExitWaitTime(time.Microsecond*10)) 56 svr := genericserver.NewServer(handler, g, opts...) 57 go func() { 58 err := svr.Run() 59 if err != nil { 60 panic(err) 61 } 62 }() 63 test.WaitServerStart(addr.String()) 64 return svr 65 } 66 67 // GenericServiceImpl ... 68 type GenericServiceImpl struct{} 69 70 // GenericCall ... 71 func (g *GenericServiceImpl) GenericCall(ctx context.Context, method string, request interface{}) (response interface{}, err error) { 72 req := request.([]byte) 73 fmt.Printf("Recv: %v\n", string(req[8+len(method):])) 74 75 buf := genBinaryResp(method) 76 return buf, nil 77 } 78 79 // GenericServiceErrorImpl ... 80 type GenericServiceErrorImpl struct{} 81 82 // GenericCall ... 83 func (g *GenericServiceErrorImpl) GenericCall(ctx context.Context, method string, request interface{}) (response interface{}, err error) { 84 return response, errors.New(errResp) 85 } 86 87 // GenericServiceMockImpl ... 88 type GenericServiceMockImpl struct{} 89 90 // GenericCall ... 91 func (g *GenericServiceMockImpl) GenericCall(ctx context.Context, method string, request interface{}) (response interface{}, err error) { 92 rc := utils.NewThriftMessageCodec() 93 buf := request.([]byte) 94 95 var args2 kt.MockTestArgs 96 mth, seqID, err := rc.Decode(buf, &args2) 97 if err != nil { 98 return nil, err 99 } 100 101 if args2.Req.Msg != reqMsg { 102 return nil, fmt.Errorf("msg is not %s", reqMsg) 103 } 104 105 resp := respMsg 106 result := kt.NewMockTestResult() 107 result.Success = &resp 108 109 buf, err = rc.Encode(mth, thrift.REPLY, seqID, result) 110 return buf, err 111 } 112 113 // NewMockServer normal server 114 func NewMockServer(handler kt.Mock, addr net.Addr, opts ...server.Option) server.Server { 115 var options []server.Option 116 opts = append(opts, server.WithServiceAddr(addr), server.WithExitWaitTime(time.Microsecond*10)) 117 options = append(options, opts...) 118 119 svr := server.NewServer(options...) 120 if err := svr.RegisterService(serviceInfo(), handler); err != nil { 121 panic(err) 122 } 123 go func() { 124 err := svr.Run() 125 if err != nil { 126 panic(err) 127 } 128 }() 129 test.WaitServerStart(addr.String()) 130 return svr 131 } 132 133 func serviceInfo() *serviceinfo.ServiceInfo { 134 destService := "Mock" 135 handlerType := (*kt.Mock)(nil) 136 methods := map[string]serviceinfo.MethodInfo{ 137 "Test": serviceinfo.NewMethodInfo(testHandler, newMockTestArgs, newMockTestResult, false), 138 } 139 svcInfo := &serviceinfo.ServiceInfo{ 140 ServiceName: destService, 141 HandlerType: handlerType, 142 Methods: methods, 143 Extra: make(map[string]interface{}), 144 } 145 return svcInfo 146 } 147 148 func newMockTestArgs() interface{} { 149 return kt.NewMockTestArgs() 150 } 151 152 func newMockTestResult() interface{} { 153 return kt.NewMockTestResult() 154 } 155 156 func testHandler(ctx context.Context, handler, arg, result interface{}) error { 157 realArg := arg.(*kt.MockTestArgs) 158 realResult := result.(*kt.MockTestResult) 159 success, err := handler.(kt.Mock).Test(ctx, realArg.Req) 160 if err != nil { 161 return err 162 } 163 realResult.Success = &success 164 return nil 165 } 166 167 // MockImpl is used for test 168 type MockImpl struct{} 169 170 // Test ... 171 func (m *MockImpl) Test(ctx context.Context, req *kt.MockReq) (r string, err error) { 172 if req.Msg != reqMsg { 173 return "", fmt.Errorf("msg is not %s", reqMsg) 174 } 175 return respMsg, nil 176 } 177 178 // ExceptionTest ... 179 func (m *MockImpl) ExceptionTest(ctx context.Context, req *kt.MockReq) (r string, err error) { 180 return "", kt.NewException() 181 } 182 183 func genBinaryResp(method string) []byte { 184 idx := 0 185 buf := make([]byte, 12+len(method)+len(respMsg)) 186 binary.BigEndian.PutUint32(buf, thrift.VERSION_1) 187 idx += 4 188 binary.BigEndian.PutUint32(buf[idx:idx+4], uint32(len(method))) 189 idx += 4 190 copy(buf[idx:idx+len(method)], method) 191 idx += len(method) 192 binary.BigEndian.PutUint32(buf[idx:idx+4], 100) 193 idx += 4 194 copy(buf[idx:idx+len(respMsg)], respMsg) 195 return buf 196 }