github.com/matrixorigin/matrixone@v0.7.0/pkg/common/morpc/server_test.go (about)

     1  // Copyright 2021 - 2022 Matrix Origin
     2  //
     3  // Licensed under the Apache License, Version 2.0 (the "License");
     4  // you may not use this file except in compliance with the License.
     5  // You may obtain a copy of the License at
     6  //
     7  //      http://www.apache.org/licenses/LICENSE-2.0
     8  //
     9  // Unless required by applicable law or agreed to in writing, software
    10  // distributed under the License is distributed on an "AS IS" BASIS,
    11  // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    12  // See the License for the specific language governing permissions and
    13  // limitations under the License.
    14  
    15  package morpc
    16  
    17  import (
    18  	"context"
    19  	"os"
    20  	"sync"
    21  	"testing"
    22  	"time"
    23  
    24  	"github.com/fagongzi/goetty/v2"
    25  	"github.com/matrixorigin/matrixone/pkg/logutil"
    26  	"github.com/stretchr/testify/assert"
    27  	"go.uber.org/zap"
    28  )
    29  
    30  func TestCreateServerWithOptions(t *testing.T) {
    31  	testRPCServer(t, func(rs *server) {
    32  		assert.Equal(t, 100, rs.options.batchSendSize)
    33  		assert.Equal(t, 200, rs.options.bufferSize)
    34  	}, WithServerBatchSendSize(100),
    35  		WithServerSessionBufferSize(200))
    36  }
    37  
    38  func TestHandleServer(t *testing.T) {
    39  	testRPCServer(t, func(rs *server) {
    40  		c := newTestClient(t)
    41  		defer func() {
    42  			assert.NoError(t, c.Close())
    43  		}()
    44  
    45  		ctx, cancel := context.WithTimeout(context.Background(), time.Second*10000)
    46  		defer cancel()
    47  
    48  		rs.RegisterRequestHandler(func(_ context.Context, request Message, sequence uint64, cs ClientSession) error {
    49  			return cs.Write(ctx, request)
    50  		})
    51  
    52  		req := newTestMessage(1)
    53  		f, err := c.Send(ctx, testAddr, req)
    54  		assert.NoError(t, err)
    55  
    56  		defer f.Close()
    57  		resp, err := f.Get()
    58  		assert.NoError(t, err)
    59  		assert.Equal(t, req, resp)
    60  	})
    61  }
    62  
    63  func TestHandleServerWithPayloadMessage(t *testing.T) {
    64  	testRPCServer(t, func(rs *server) {
    65  		c := newTestClient(t)
    66  		defer func() {
    67  			assert.NoError(t, c.Close())
    68  		}()
    69  
    70  		ctx, cancel := context.WithTimeout(context.Background(), time.Second*10)
    71  		defer cancel()
    72  
    73  		rs.RegisterRequestHandler(func(_ context.Context, request Message, sequence uint64, cs ClientSession) error {
    74  			return cs.Write(ctx, request)
    75  		})
    76  
    77  		req := &testMessage{id: 1, payload: []byte("payload")}
    78  		f, err := c.Send(ctx, testAddr, req)
    79  		assert.NoError(t, err)
    80  
    81  		defer f.Close()
    82  		resp, err := f.Get()
    83  		assert.NoError(t, err)
    84  		assert.Equal(t, req, resp)
    85  	})
    86  }
    87  
    88  func TestHandleServerWriteWithClosedSession(t *testing.T) {
    89  	wc := make(chan struct{}, 1)
    90  	defer close(wc)
    91  
    92  	testRPCServer(t, func(rs *server) {
    93  		ctx, cancel := context.WithTimeout(context.Background(), time.Second*2)
    94  		defer cancel()
    95  
    96  		c := newTestClient(t)
    97  		rs.RegisterRequestHandler(func(_ context.Context, request Message, _ uint64, cs ClientSession) error {
    98  			assert.NoError(t, c.Close())
    99  			return cs.Write(ctx, request)
   100  		})
   101  
   102  		req := newTestMessage(1)
   103  		f, err := c.Send(ctx, testAddr, req)
   104  		assert.NoError(t, err)
   105  
   106  		defer f.Close()
   107  		resp, err := f.Get()
   108  		assert.Error(t, ctx.Err(), err)
   109  		assert.Nil(t, resp)
   110  	})
   111  }
   112  
   113  func TestStreamServer(t *testing.T) {
   114  	testRPCServer(t, func(rs *server) {
   115  		ctx, cancel := context.WithTimeout(context.TODO(), time.Second*10)
   116  		defer cancel()
   117  
   118  		c := newTestClient(t)
   119  		defer func() {
   120  			assert.NoError(t, c.Close())
   121  		}()
   122  
   123  		wg := sync.WaitGroup{}
   124  		wg.Add(1)
   125  		n := 10
   126  		rs.RegisterRequestHandler(func(_ context.Context, request Message, _ uint64, cs ClientSession) error {
   127  			go func() {
   128  				defer wg.Done()
   129  				for i := 0; i < n; i++ {
   130  					assert.NoError(t, cs.Write(ctx, request))
   131  				}
   132  			}()
   133  			return nil
   134  		})
   135  
   136  		st, err := c.NewStream(testAddr, false)
   137  		assert.NoError(t, err)
   138  		defer func() {
   139  			assert.NoError(t, st.Close())
   140  		}()
   141  
   142  		req := newTestMessage(st.ID())
   143  		assert.NoError(t, st.Send(ctx, req))
   144  
   145  		rc, err := st.Receive()
   146  		assert.NoError(t, err)
   147  		for i := 0; i < n; i++ {
   148  			assert.Equal(t, req, <-rc)
   149  		}
   150  
   151  		wg.Wait()
   152  	})
   153  }
   154  
   155  func TestStreamServerWithSequenceNotMatch(t *testing.T) {
   156  	testRPCServer(t, func(rs *server) {
   157  		ctx, cancel := context.WithTimeout(context.TODO(), time.Second*10)
   158  		defer cancel()
   159  
   160  		c := newTestClient(t)
   161  		defer func() {
   162  			assert.NoError(t, c.Close())
   163  		}()
   164  
   165  		rs.RegisterRequestHandler(func(_ context.Context, request Message, _ uint64, cs ClientSession) error {
   166  			return cs.Write(ctx, request)
   167  		})
   168  
   169  		v, err := c.NewStream(testAddr, false)
   170  		assert.NoError(t, err)
   171  		st := v.(*stream)
   172  		defer func() {
   173  			assert.NoError(t, st.Close())
   174  		}()
   175  
   176  		st.sequence = 2
   177  		req := newTestMessage(st.ID())
   178  		assert.NoError(t, st.Send(ctx, req))
   179  
   180  		rc, err := st.Receive()
   181  		assert.NoError(t, err)
   182  		assert.NotNil(t, rc)
   183  		resp := <-rc
   184  		assert.Nil(t, resp)
   185  	})
   186  }
   187  
   188  func BenchmarkSend(b *testing.B) {
   189  	ctx, cancel := context.WithTimeout(context.Background(), time.Second*5)
   190  	defer cancel()
   191  
   192  	testRPCServer(b, func(rs *server) {
   193  		c := newTestClient(b,
   194  			WithClientMaxBackendPerHost(1),
   195  			WithClientInitBackends([]string{testAddr}, []int{1}))
   196  		defer func() {
   197  			assert.NoError(b, c.Close())
   198  		}()
   199  
   200  		rs.RegisterRequestHandler(func(_ context.Context, request Message, sequence uint64, cs ClientSession) error {
   201  			return cs.Write(ctx, request)
   202  		})
   203  
   204  		req := newTestMessage(1)
   205  
   206  		b.ResetTimer()
   207  		for i := 0; i < b.N; i++ {
   208  			f, err := c.Send(ctx, testAddr, req)
   209  			if err == nil {
   210  				_, err := f.Get()
   211  				if err != nil {
   212  					assert.Equal(b, ctx.Err(), err)
   213  				}
   214  				f.Close()
   215  			}
   216  		}
   217  	}, WithServerGoettyOptions(goetty.WithSessionReleaseMsgFunc(func(i interface{}) {
   218  		msg := i.(RPCMessage)
   219  		if !msg.InternalMessage() {
   220  			messagePool.Put(msg.Message)
   221  		}
   222  	})))
   223  }
   224  
   225  func testRPCServer(t assert.TestingT, testFunc func(*server), options ...ServerOption) {
   226  	assert.NoError(t, os.RemoveAll(testUnixFile))
   227  
   228  	options = append(options,
   229  		WithServerLogger(logutil.GetPanicLoggerWithLevel(zap.InfoLevel)))
   230  	s, err := NewRPCServer("test", testAddr, newTestCodec(), options...)
   231  	assert.NoError(t, err)
   232  	assert.NoError(t, s.Start())
   233  	defer func() {
   234  		assert.NoError(t, s.Close())
   235  	}()
   236  
   237  	testFunc(s.(*server))
   238  }
   239  
   240  func newTestClient(t assert.TestingT, options ...ClientOption) RPCClient {
   241  	bf := NewGoettyBasedBackendFactory(newTestCodec())
   242  	c, err := NewClient(bf, options...)
   243  	assert.NoError(t, err)
   244  	return c
   245  }
   246  
   247  func TestPing(t *testing.T) {
   248  	testRPCServer(t, func(rs *server) {
   249  		c := newTestClient(t)
   250  		defer func() {
   251  			assert.NoError(t, c.Close())
   252  		}()
   253  
   254  		ctx, cancel := context.WithTimeout(context.Background(), time.Second*5)
   255  		defer cancel()
   256  
   257  		assert.NoError(t, c.Ping(ctx, testAddr))
   258  	})
   259  }