github.com/matrixorigin/matrixone@v1.2.0/pkg/txn/rpc/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 rpc
    16  
    17  import (
    18  	"context"
    19  	"os"
    20  	"testing"
    21  	"time"
    22  
    23  	"github.com/matrixorigin/matrixone/pkg/common/morpc"
    24  	"github.com/matrixorigin/matrixone/pkg/common/runtime"
    25  	"github.com/matrixorigin/matrixone/pkg/logutil"
    26  	"github.com/matrixorigin/matrixone/pkg/pb/metadata"
    27  	"github.com/matrixorigin/matrixone/pkg/pb/txn"
    28  	"github.com/matrixorigin/matrixone/pkg/txn/clock"
    29  	"github.com/matrixorigin/matrixone/pkg/util/toml"
    30  	"github.com/stretchr/testify/assert"
    31  	"go.uber.org/zap"
    32  )
    33  
    34  func TestHandleMessageWithSender(t *testing.T) {
    35  	runTestTxnServer(t, testTN1Addr, func(s *server) {
    36  		s.RegisterMethodHandler(txn.TxnMethod_Read, func(ctx context.Context, tr1 *txn.TxnRequest, tr2 *txn.TxnResponse) error {
    37  			return nil
    38  		})
    39  
    40  		rt := newTestRuntime(newTestClock(), s.rt.Logger().RawLogger())
    41  		runtime.SetupProcessLevelRuntime(rt)
    42  		cli, err := NewSender(Config{EnableCompress: true}, rt)
    43  		assert.NoError(t, err)
    44  		defer func() {
    45  			assert.NoError(t, cli.Close())
    46  		}()
    47  
    48  		ctx, cancel := context.WithTimeout(context.Background(), time.Hour)
    49  		defer cancel()
    50  
    51  		v, err := cli.Send(ctx, []txn.TxnRequest{{CNRequest: &txn.CNOpRequest{Target: metadata.TNShard{Address: testTN1Addr}}}})
    52  		assert.NoError(t, err)
    53  		assert.Equal(t, 1, len(v.Responses))
    54  	}, WithServerEnableCompress(true))
    55  }
    56  
    57  func TestHandleMessageEnableCompressWithSender(t *testing.T) {
    58  	runTestTxnServer(t, testTN1Addr, func(s *server) {
    59  		s.RegisterMethodHandler(txn.TxnMethod_Read, func(ctx context.Context, tr1 *txn.TxnRequest, tr2 *txn.TxnResponse) error {
    60  			return nil
    61  		})
    62  
    63  		cli, err := NewSender(Config{}, newTestRuntime(newTestClock(), s.rt.Logger().RawLogger()))
    64  		assert.NoError(t, err)
    65  		defer func() {
    66  			assert.NoError(t, cli.Close())
    67  		}()
    68  
    69  		ctx, cancel := context.WithTimeout(context.Background(), time.Hour)
    70  		defer cancel()
    71  
    72  		v, err := cli.Send(ctx, []txn.TxnRequest{{CNRequest: &txn.CNOpRequest{Target: metadata.TNShard{Address: testTN1Addr}}}})
    73  		assert.NoError(t, err)
    74  		assert.Equal(t, 1, len(v.Responses))
    75  	})
    76  }
    77  
    78  func TestHandleLargeMessageWithSender(t *testing.T) {
    79  	size := 1024 * 1024 * 15
    80  	runTestTxnServer(t, testTN1Addr, func(s *server) {
    81  		s.RegisterMethodHandler(txn.TxnMethod_Read, func(ctx context.Context, tr1 *txn.TxnRequest, tr2 *txn.TxnResponse) error {
    82  			tr2.CNOpResponse = &txn.CNOpResponse{Payload: make([]byte, size)}
    83  			return nil
    84  		})
    85  
    86  		cli, err := NewSender(Config{MaxMessageSize: toml.ByteSize(size + 1024)},
    87  			newTestRuntime(newTestClock(), s.rt.Logger().RawLogger()))
    88  		assert.NoError(t, err)
    89  		defer func() {
    90  			assert.NoError(t, cli.Close())
    91  		}()
    92  
    93  		ctx, cancel := context.WithTimeout(context.Background(), time.Hour)
    94  		defer cancel()
    95  
    96  		v, err := cli.Send(ctx, []txn.TxnRequest{{
    97  			CNRequest: &txn.CNOpRequest{
    98  				Target:  metadata.TNShard{Address: testTN1Addr},
    99  				Payload: make([]byte, size),
   100  			},
   101  		}})
   102  		assert.NoError(t, err)
   103  		assert.Equal(t, 1, len(v.Responses))
   104  	}, WithServerMaxMessageSize(size+1024))
   105  }
   106  
   107  func TestHandleMessage(t *testing.T) {
   108  	runTestTxnServer(t, testTN1Addr, func(s *server) {
   109  		s.RegisterMethodHandler(txn.TxnMethod_Read, func(ctx context.Context, tr1 *txn.TxnRequest, tr2 *txn.TxnResponse) error {
   110  			return nil
   111  		})
   112  
   113  		c := make(chan morpc.Message, 1)
   114  		defer close(c)
   115  		cs := newTestClientSession(c)
   116  
   117  		ctx, cancel := context.WithTimeout(context.Background(), time.Hour)
   118  		defer cancel()
   119  		assert.NoError(t, s.onMessage(ctx, newMessage(&txn.TxnRequest{RequestID: 1}), 0, cs))
   120  		v := <-c
   121  		assert.Equal(t, uint64(1), v.GetID())
   122  	})
   123  }
   124  
   125  func TestHandleMessageWithFilter(t *testing.T) {
   126  	runTestTxnServer(t, testTN1Addr, func(s *server) {
   127  		n := 0
   128  		s.RegisterMethodHandler(txn.TxnMethod_Read, func(_ context.Context, _ *txn.TxnRequest, _ *txn.TxnResponse) error {
   129  			n++
   130  			return nil
   131  		})
   132  
   133  		ctx, cancel := context.WithTimeout(context.Background(), time.Hour)
   134  		defer cancel()
   135  		assert.NoError(t, s.onMessage(ctx, newMessage(&txn.TxnRequest{RequestID: 1}),
   136  			0, nil))
   137  		assert.Equal(t, 0, n)
   138  	}, WithServerMessageFilter(func(tr *txn.TxnRequest) bool {
   139  		return false
   140  	}))
   141  }
   142  
   143  func TestHandleInvalidMessageWillPanic(t *testing.T) {
   144  	runTestTxnServer(t, testTN1Addr, func(s *server) {
   145  		defer func() {
   146  			if err := recover(); err != nil {
   147  				return
   148  			}
   149  			assert.Fail(t, "must panic")
   150  		}()
   151  		ctx, cancel := context.WithTimeout(context.Background(), time.Hour)
   152  		defer cancel()
   153  		assert.NoError(t, s.onMessage(ctx, newMessage(&txn.TxnResponse{}), 0, nil))
   154  	})
   155  }
   156  
   157  func TestHandleNotRegisterWillReturnError(t *testing.T) {
   158  	runTestTxnServer(t, testTN1Addr, func(s *server) {
   159  		assert.Error(t, s.onMessage(context.Background(), newMessage(&txn.TxnRequest{}), 0, nil))
   160  	})
   161  }
   162  
   163  func TestTimeoutRequestCannotHandled(t *testing.T) {
   164  	runTestTxnServer(t, testTN1Addr, func(s *server) {
   165  		n := 0
   166  		s.RegisterMethodHandler(txn.TxnMethod_Read,
   167  			func(_ context.Context, _ *txn.TxnRequest, _ *txn.TxnResponse) error {
   168  				n++
   169  				return nil
   170  			})
   171  
   172  		ctx, cancel := context.WithTimeout(context.Background(), 1)
   173  		cancel()
   174  		req := &txn.TxnRequest{Method: txn.TxnMethod_Read}
   175  		assert.NoError(t, s.onMessage(ctx, newMessage(req), 0, nil))
   176  		assert.Equal(t, 0, n)
   177  	})
   178  }
   179  
   180  func runTestTxnServer(t *testing.T, addr string, testFunc func(s *server), opts ...ServerOption) {
   181  	assert.NoError(t, os.RemoveAll(addr[7:]))
   182  	opts = append(opts,
   183  		WithServerQueueBufferSize(100),
   184  		WithServerQueueWorkers(2))
   185  	s, err := NewTxnServer(addr,
   186  		newTestRuntime(clock.NewHLCClock(func() int64 { return 0 }, 0), logutil.GetPanicLogger()),
   187  		opts...)
   188  	assert.NoError(t, err)
   189  	defer func() {
   190  		assert.NoError(t, s.Close())
   191  	}()
   192  	assert.NoError(t, s.Start())
   193  
   194  	testFunc(s.(*server))
   195  }
   196  
   197  type testClientSession struct {
   198  	c chan morpc.Message
   199  }
   200  
   201  func newTestClientSession(c chan morpc.Message) *testClientSession {
   202  	return &testClientSession{
   203  		c: c,
   204  	}
   205  }
   206  
   207  func (cs *testClientSession) RemoteAddress() string {
   208  	return ""
   209  }
   210  
   211  func (cs *testClientSession) Close() error {
   212  	return nil
   213  }
   214  
   215  func (cs *testClientSession) Write(ctx context.Context, response morpc.Message) error {
   216  	cs.c <- response
   217  	return nil
   218  }
   219  
   220  func (cs *testClientSession) AsyncWrite(response morpc.Message) error {
   221  	return nil
   222  }
   223  
   224  func (cs *testClientSession) CreateCache(
   225  	ctx context.Context,
   226  	cacheID uint64) (morpc.MessageCache, error) {
   227  	panic("not implement")
   228  }
   229  
   230  func (cs *testClientSession) DeleteCache(cacheID uint64) {
   231  	panic("not implement")
   232  }
   233  
   234  func (cs *testClientSession) GetCache(cacheID uint64) (morpc.MessageCache, error) {
   235  	panic("not implement")
   236  }
   237  
   238  func newTestClock() clock.Clock {
   239  	return clock.NewHLCClock(func() int64 { return 0 }, 0)
   240  }
   241  
   242  func newTestRuntime(clock clock.Clock, logger *zap.Logger) runtime.Runtime {
   243  	return runtime.NewRuntime(metadata.ServiceType_CN, "", logutil.Adjust(logger), runtime.WithClock(clock))
   244  }
   245  
   246  func newMessage(req morpc.Message) morpc.RPCMessage {
   247  	ctx, cancel := context.WithCancel(context.Background())
   248  	return morpc.RPCMessage{
   249  		Ctx:     ctx,
   250  		Cancel:  cancel,
   251  		Message: req,
   252  	}
   253  }