github.com/cloudwego/kitex@v0.9.0/pkg/remote/trans/netpollmux/client_handler_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 netpollmux
    18  
    19  import (
    20  	"context"
    21  	"strings"
    22  	"testing"
    23  	"time"
    24  
    25  	"github.com/cloudwego/netpoll"
    26  
    27  	"github.com/cloudwego/kitex/internal/test"
    28  	"github.com/cloudwego/kitex/pkg/remote"
    29  	"github.com/cloudwego/kitex/pkg/remote/codec"
    30  	"github.com/cloudwego/kitex/pkg/remote/trans"
    31  	np "github.com/cloudwego/kitex/pkg/remote/trans/netpoll"
    32  	"github.com/cloudwego/kitex/pkg/rpcinfo"
    33  	"github.com/cloudwego/kitex/pkg/serviceinfo"
    34  )
    35  
    36  func newTestRemoteClientOptionWithInStr(s string) *remote.ClientOption {
    37  	opt := &remote.ClientOption{
    38  		Codec: &MockCodec{
    39  			EncodeFunc: func(ctx context.Context, msg remote.Message, out remote.ByteBuffer) error {
    40  				r := mockHeader(msg.RPCInfo().Invocation().SeqID(), s)
    41  				_, err := out.WriteBinary(r.Bytes())
    42  				return err
    43  			},
    44  			DecodeFunc: func(ctx context.Context, msg remote.Message, in remote.ByteBuffer) error {
    45  				in.Skip(3 * codec.Size32)
    46  				_, err := in.ReadString(len(s))
    47  				return err
    48  			},
    49  		},
    50  		ConnPool: NewMuxConnPool(1),
    51  	}
    52  	return opt
    53  }
    54  
    55  func TestNewCliTransHandler(t *testing.T) {
    56  	// check success
    57  	handler, err := NewCliTransHandlerFactory().NewTransHandler(&remote.ClientOption{
    58  		ConnPool: &MuxPool{},
    59  	})
    60  	test.Assert(t, err == nil, err)
    61  	test.Assert(t, handler != nil)
    62  	// check fail
    63  	handler, err = NewCliTransHandlerFactory().NewTransHandler(&remote.ClientOption{})
    64  	test.Assert(t, err != nil)
    65  	test.Assert(t, handler == nil)
    66  }
    67  
    68  func TestCliTransHandler(t *testing.T) {
    69  	s := "hello world"
    70  	opt := &remote.ClientOption{
    71  		Codec: &MockCodec{
    72  			EncodeFunc: func(ctx context.Context, msg remote.Message, out remote.ByteBuffer) error {
    73  				r := mockHeader(msg.RPCInfo().Invocation().SeqID(), s)
    74  				n, err := out.WriteBinary(r.Bytes())
    75  				test.Assert(t, err == nil, err)
    76  				test.Assert(t, n == r.Len(), n, r.Len())
    77  				return err
    78  			},
    79  			DecodeFunc: func(ctx context.Context, msg remote.Message, in remote.ByteBuffer) error {
    80  				l := in.ReadableLen()
    81  				test.Assert(t, l == 3*codec.Size32+len(s))
    82  				in.Skip(3 * codec.Size32)
    83  				got, err := in.ReadString(len(s))
    84  				test.Assert(t, err == nil, err)
    85  				test.Assert(t, got == s, got, s)
    86  				return err
    87  			},
    88  		},
    89  		ConnPool: NewMuxConnPool(1),
    90  	}
    91  
    92  	handler, err := NewCliTransHandlerFactory().NewTransHandler(opt)
    93  	test.Assert(t, err == nil)
    94  
    95  	ctx := context.Background()
    96  	buf := netpoll.NewLinkBuffer(1024)
    97  	npconn := &MockNetpollConn{
    98  		ReaderFunc: func() (r netpoll.Reader) {
    99  			return buf
   100  		},
   101  		WriterFunc: func() (r netpoll.Writer) {
   102  			return buf
   103  		},
   104  	}
   105  	conn := newMuxCliConn(npconn)
   106  
   107  	ri := newMockRPCInfo()
   108  	msg := &MockMessage{
   109  		RPCInfoFunc: func() rpcinfo.RPCInfo {
   110  			return ri
   111  		},
   112  		ServiceInfoFunc: func() *serviceinfo.ServiceInfo {
   113  			return &serviceinfo.ServiceInfo{
   114  				Methods: map[string]serviceinfo.MethodInfo{
   115  					"method": serviceinfo.NewMethodInfo(nil, nil, nil, false),
   116  				},
   117  			}
   118  		},
   119  	}
   120  	ctx, err = handler.Write(ctx, conn, msg)
   121  	test.Assert(t, ctx != nil, ctx)
   122  	test.Assert(t, err == nil, err)
   123  
   124  	time.Sleep(5 * time.Millisecond)
   125  	buf.Flush()
   126  	test.Assert(t, buf.Len() > len(s), buf.Len())
   127  
   128  	err = conn.OnRequest(ctx, npconn)
   129  	test.Assert(t, err == nil, err)
   130  
   131  	ctx, err = handler.Read(ctx, conn, msg)
   132  	test.Assert(t, ctx != nil, ctx)
   133  	test.Assert(t, err == nil, err)
   134  }
   135  
   136  // TestWriteNoMethod test client_handler write return unknown method err
   137  func TestWriteNoMethod(t *testing.T) {
   138  	// 1. prepare mock data
   139  	s := "hello world"
   140  	opt := newTestRemoteClientOptionWithInStr(s)
   141  
   142  	handler, err := NewCliTransHandlerFactory().NewTransHandler(opt)
   143  	test.Assert(t, err == nil)
   144  
   145  	ctx := context.Background()
   146  
   147  	var isWriteBufFlushed bool
   148  
   149  	buf := netpoll.NewLinkBuffer(1024)
   150  	npconn := &MockNetpollConn{
   151  		ReaderFunc: func() (r netpoll.Reader) {
   152  			return buf
   153  		},
   154  		WriterFunc: func() (r netpoll.Writer) {
   155  			isWriteBufFlushed = true
   156  			return buf
   157  		},
   158  	}
   159  	conn := newMuxCliConn(npconn)
   160  
   161  	ri := newMockRPCInfo()
   162  	msg := &MockMessage{
   163  		RPCInfoFunc: func() rpcinfo.RPCInfo {
   164  			return ri
   165  		},
   166  		ServiceInfoFunc: func() *serviceinfo.ServiceInfo {
   167  			return &serviceinfo.ServiceInfo{}
   168  		},
   169  	}
   170  
   171  	// 2. test
   172  	ctx, err = handler.Write(ctx, conn, msg)
   173  	// check ctx/err not nil
   174  	test.Assert(t, ctx != nil, ctx)
   175  	test.Assert(t, err != nil, err)
   176  	tErr, ok := err.(*remote.TransError)
   177  	test.Assert(t, ok)
   178  	test.Assert(t, tErr.TypeID() == remote.UnknownMethod)
   179  	test.Assert(t, !isWriteBufFlushed)
   180  }
   181  
   182  // TestWriteOneWayMethod test client_handler write oneway method
   183  func TestWriteOneWayMethod(t *testing.T) {
   184  	// 1. prepare mock data
   185  	s := "hello world"
   186  	opt := newTestRemoteClientOptionWithInStr(s)
   187  
   188  	handler, err := NewCliTransHandlerFactory().NewTransHandler(opt)
   189  	test.Assert(t, err == nil)
   190  
   191  	ctx := context.Background()
   192  	ri := newMockRPCInfo()
   193  
   194  	buf := netpoll.NewLinkBuffer(2048)
   195  	var isWrite bool
   196  	var isRead bool
   197  	npconn := &MockNetpollConn{
   198  		ReaderFunc: func() (r netpoll.Reader) {
   199  			isRead = true
   200  			return buf
   201  		},
   202  		WriterFunc: func() (r netpoll.Writer) {
   203  			isWrite = true
   204  			return buf
   205  		},
   206  	}
   207  	conn := newMuxCliConn(npconn)
   208  
   209  	oneWayMsg := &MockMessage{
   210  		RPCInfoFunc: func() rpcinfo.RPCInfo {
   211  			return ri
   212  		},
   213  		ServiceInfoFunc: func() *serviceinfo.ServiceInfo {
   214  			return &serviceinfo.ServiceInfo{
   215  				Methods: map[string]serviceinfo.MethodInfo{
   216  					"method": serviceinfo.NewMethodInfo(nil, nil, nil, true),
   217  				},
   218  			}
   219  		},
   220  	}
   221  	ctx, err = handler.Write(ctx, conn, oneWayMsg)
   222  	test.Assert(t, ctx != nil, ctx)
   223  	test.Assert(t, err == nil, err)
   224  
   225  	time.Sleep(5 * time.Millisecond)
   226  	buf.Flush()
   227  	test.Assert(t, isWrite)
   228  	test.Assert(t, buf.Len() > len(s), buf.Len())
   229  
   230  	err = conn.OnRequest(ctx, npconn)
   231  	test.Assert(t, err == nil, err)
   232  
   233  	test.Assert(t, isRead)
   234  }
   235  
   236  // TestReadTimeout test client_handler read timeout because of no execute OnRequest
   237  func TestReadTimeout(t *testing.T) {
   238  	s := "hello world"
   239  	opt := newTestRemoteClientOptionWithInStr(s)
   240  
   241  	handler, err := NewCliTransHandlerFactory().NewTransHandler(opt)
   242  	test.Assert(t, err == nil, err)
   243  
   244  	ctx := context.Background()
   245  	buf := netpoll.NewLinkBuffer(1024)
   246  
   247  	var isRead, isWrite bool
   248  
   249  	npconn := &MockNetpollConn{
   250  		ReaderFunc: func() (r netpoll.Reader) {
   251  			isRead = true
   252  			return buf
   253  		},
   254  		WriterFunc: func() (r netpoll.Writer) {
   255  			isWrite = true
   256  			return buf
   257  		},
   258  	}
   259  	conn := newMuxCliConn(npconn)
   260  
   261  	cfg := rpcinfo.NewRPCConfig()
   262  	rwTimeout := 1 * time.Second
   263  	rpcinfo.AsMutableRPCConfig(cfg).SetRPCTimeout(rwTimeout)
   264  
   265  	method := "method"
   266  	c := rpcinfo.NewEndpointInfo("", method, nil, nil)
   267  	to := rpcinfo.NewEndpointInfo("", method, nil, nil)
   268  	ri := rpcinfo.NewRPCInfo(c, to, rpcinfo.NewInvocation("", method), cfg, rpcinfo.NewRPCStats())
   269  	msg := &MockMessage{
   270  		RPCInfoFunc: func() rpcinfo.RPCInfo {
   271  			return ri
   272  		},
   273  		ServiceInfoFunc: func() *serviceinfo.ServiceInfo {
   274  			return &serviceinfo.ServiceInfo{
   275  				Methods: map[string]serviceinfo.MethodInfo{
   276  					"method": serviceinfo.NewMethodInfo(nil, nil, nil, false),
   277  				},
   278  			}
   279  		},
   280  	}
   281  
   282  	ctx, err = handler.Write(ctx, conn, msg)
   283  	test.Assert(t, ctx != nil, ctx)
   284  	test.Assert(t, err == nil, err)
   285  
   286  	time.Sleep(5 * time.Millisecond)
   287  	buf.Flush()
   288  	test.Assert(t, isWrite)
   289  	test.Assert(t, buf.Len() > len(s), buf.Len())
   290  
   291  	ctx, err = handler.Read(ctx, conn, msg)
   292  	test.Assert(t, rwTimeout <= trans.GetReadTimeout(ri.Config()))
   293  	test.Assert(t, ctx != nil, ctx)
   294  	test.Assert(t, err != nil, err)
   295  	test.Assert(t, strings.Contains(err.Error(), "recv wait timeout"))
   296  	test.Assert(t, !isRead)
   297  
   298  	handler.OnError(ctx, err, conn)
   299  }
   300  
   301  // TestCallbackClose test asyncCallback Close
   302  func TestCallbackClose(t *testing.T) {
   303  	buf := netpoll.NewLinkBuffer()
   304  	bufWriter := np.NewWriterByteBuffer(buf)
   305  	callback := newAsyncCallback(buf, bufWriter)
   306  	callback.Close()
   307  }