github.com/matrixorigin/matrixone@v0.7.0/pkg/common/morpc/codec_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  	"io"
    20  	"strings"
    21  	"testing"
    22  	"time"
    23  
    24  	"github.com/fagongzi/goetty/v2/buf"
    25  	"github.com/matrixorigin/matrixone/pkg/common/mpool"
    26  	"github.com/matrixorigin/matrixone/pkg/common/stopper"
    27  	"github.com/matrixorigin/matrixone/pkg/txn/clock"
    28  	"github.com/stretchr/testify/assert"
    29  	"github.com/stretchr/testify/require"
    30  )
    31  
    32  func TestEncodeAndDecode(t *testing.T) {
    33  	codec := newTestCodec()
    34  	buf := buf.NewByteBuf(1)
    35  
    36  	ctx, cancel := context.WithTimeout(context.TODO(), time.Hour*10)
    37  	defer cancel()
    38  
    39  	msg := RPCMessage{Ctx: ctx, Message: newTestMessage(1)}
    40  	err := codec.Encode(msg, buf, nil)
    41  	assert.NoError(t, err)
    42  
    43  	v, ok, err := codec.Decode(buf)
    44  	assert.True(t, ok)
    45  	assert.Equal(t, msg.Message, v.(RPCMessage).Message)
    46  	assert.NoError(t, err)
    47  	assert.NotNil(t, v.(RPCMessage).Ctx)
    48  	assert.NotNil(t, v.(RPCMessage).cancel)
    49  }
    50  
    51  func TestEncodeAndDecodeWithStream(t *testing.T) {
    52  	codec := newTestCodec()
    53  	buf := buf.NewByteBuf(1)
    54  
    55  	ctx, cancel := context.WithTimeout(context.TODO(), time.Hour*10)
    56  	defer cancel()
    57  
    58  	msg := RPCMessage{Ctx: ctx, Message: newTestMessage(1), stream: true, streamSequence: 1}
    59  	err := codec.Encode(msg, buf, nil)
    60  	assert.NoError(t, err)
    61  
    62  	v, ok, err := codec.Decode(buf)
    63  	assert.True(t, ok)
    64  	assert.Equal(t, msg.Message, v.(RPCMessage).Message)
    65  	assert.True(t, v.(RPCMessage).stream)
    66  	assert.Equal(t, uint32(1), v.(RPCMessage).streamSequence)
    67  	assert.NoError(t, err)
    68  	assert.NotNil(t, v.(RPCMessage).Ctx)
    69  	assert.NotNil(t, v.(RPCMessage).cancel)
    70  }
    71  
    72  func TestEncodeAndDecodeWithChecksum(t *testing.T) {
    73  	ctx, cancel := context.WithTimeout(context.TODO(), time.Hour*10)
    74  	defer cancel()
    75  	codec := newTestCodec(WithCodecEnableChecksum(),
    76  		WithCodecIntegrationHLC(clock.NewHLCClock(func() int64 { return 0 }, 0)))
    77  	buf1 := buf.NewByteBuf(32)
    78  
    79  	msg := newTestMessage(1)
    80  	err := codec.Encode(RPCMessage{Ctx: ctx, Message: msg}, buf1, nil)
    81  	assert.NoError(t, err)
    82  
    83  	buf.Uint64ToBytesTo(0, buf1.RawSlice(5, 5+8))
    84  	_, ok, err := codec.Decode(buf1)
    85  	assert.False(t, ok)
    86  	assert.Error(t, err)
    87  }
    88  
    89  func TestEncodeAndDecodeWithCompress(t *testing.T) {
    90  	p, err := mpool.NewMPool("test", 0, mpool.Small)
    91  	require.NoError(t, err)
    92  
    93  	ctx, cancel := context.WithTimeout(context.TODO(), time.Hour*10)
    94  	defer cancel()
    95  	codec := newTestCodec(WithCodecEnableCompress(p))
    96  	buf1 := buf.NewByteBuf(32)
    97  
    98  	msg := newTestMessage(1)
    99  	err = codec.Encode(RPCMessage{Ctx: ctx, Message: msg}, buf1, nil)
   100  	assert.NoError(t, err)
   101  
   102  	buf.Uint64ToBytesTo(0, buf1.RawSlice(5, 5+8))
   103  	resp, ok, err := codec.Decode(buf1)
   104  	assert.NoError(t, err)
   105  	assert.True(t, ok)
   106  
   107  	assert.Equal(t, msg, resp.(RPCMessage).Message)
   108  }
   109  
   110  func TestEncodeAndDecodeWithCompressAndHasPayload(t *testing.T) {
   111  	p, err := mpool.NewMPool("test", 0, mpool.Small)
   112  	require.NoError(t, err)
   113  
   114  	ctx, cancel := context.WithTimeout(context.TODO(), time.Hour*10)
   115  	defer cancel()
   116  
   117  	codec := newTestCodec(WithCodecEnableCompress(p))
   118  	buf1 := buf.NewByteBuf(32)
   119  	buf2 := buf.NewByteBuf(32)
   120  
   121  	msg := RPCMessage{Ctx: ctx, Message: newTestMessage(1)}
   122  	msg.Message.(*testMessage).payload = []byte(strings.Repeat("payload", 100))
   123  	err = codec.Encode(msg, buf1, buf2)
   124  	assert.NoError(t, err)
   125  
   126  	v, ok, err := codec.Decode(buf2)
   127  	assert.True(t, ok)
   128  	assert.Equal(t, msg.Message, v.(RPCMessage).Message)
   129  	assert.NoError(t, err)
   130  	assert.NotNil(t, v.(RPCMessage).Ctx)
   131  	assert.NotNil(t, v.(RPCMessage).cancel)
   132  }
   133  
   134  func TestEncodeAndDecodeAndChecksumMismatch(t *testing.T) {
   135  	ctx, cancel := context.WithTimeout(context.TODO(), time.Hour*10)
   136  	defer cancel()
   137  
   138  	codec := newTestCodec(WithCodecEnableChecksum())
   139  	buf1 := buf.NewByteBuf(32)
   140  
   141  	msg := RPCMessage{Ctx: ctx, Message: newTestMessage(1)}
   142  	err := codec.Encode(msg, buf1, nil)
   143  	assert.NoError(t, err)
   144  
   145  	buf.Uint64ToBytesTo(0, buf1.RawSlice(5, 5+8))
   146  
   147  	v, ok, err := codec.Decode(buf1)
   148  	assert.False(t, ok)
   149  	assert.Error(t, err)
   150  	assert.Nil(t, v)
   151  }
   152  
   153  func TestEncodeAndDecodeWithPayload(t *testing.T) {
   154  	ctx, cancel := context.WithTimeout(context.TODO(), time.Hour*10)
   155  	defer cancel()
   156  
   157  	codec := newTestCodec()
   158  	buf1 := buf.NewByteBuf(32)
   159  	buf2 := buf.NewByteBuf(32)
   160  
   161  	msg := RPCMessage{Ctx: ctx, Message: newTestMessage(1)}
   162  	msg.Message.(*testMessage).payload = []byte("payload")
   163  	err := codec.Encode(msg, buf1, buf2)
   164  	assert.NoError(t, err)
   165  
   166  	v, ok, err := codec.Decode(buf2)
   167  	assert.True(t, ok)
   168  	assert.Equal(t, msg.Message, v.(RPCMessage).Message)
   169  	assert.NoError(t, err)
   170  	assert.NotNil(t, v.(RPCMessage).Ctx)
   171  	assert.NotNil(t, v.(RPCMessage).cancel)
   172  }
   173  
   174  func TestEncodeAndDecodeWithPayloadAndChecksum(t *testing.T) {
   175  	ctx, cancel := context.WithTimeout(context.TODO(), time.Hour*10)
   176  	defer cancel()
   177  
   178  	codec := newTestCodec(WithCodecEnableChecksum())
   179  	buf1 := buf.NewByteBuf(32)
   180  	buf2 := buf.NewByteBuf(32)
   181  
   182  	msg := RPCMessage{Ctx: ctx, Message: newTestMessage(1)}
   183  	msg.Message.(*testMessage).payload = []byte("payload")
   184  	err := codec.Encode(msg, buf1, buf2)
   185  	assert.NoError(t, err)
   186  
   187  	v, ok, err := codec.Decode(buf2)
   188  	assert.True(t, ok)
   189  	assert.Equal(t, msg.Message, v.(RPCMessage).Message)
   190  	assert.NoError(t, err)
   191  	assert.NotNil(t, v.(RPCMessage).Ctx)
   192  	assert.NotNil(t, v.(RPCMessage).cancel)
   193  }
   194  
   195  func TestEncodeAndDecodeWithEmptyPayloadAndChecksum(t *testing.T) {
   196  	ctx, cancel := context.WithTimeout(context.TODO(), time.Hour*10)
   197  	defer cancel()
   198  
   199  	codec := newTestCodec(WithCodecEnableChecksum())
   200  	buf1 := buf.NewByteBuf(32)
   201  	buf2 := buf.NewByteBuf(32)
   202  
   203  	msg := RPCMessage{Ctx: ctx, Message: newTestMessage(1)}
   204  	err := codec.Encode(msg, buf1, buf2)
   205  	assert.NoError(t, err)
   206  	io.Copy(buf2, buf1)
   207  
   208  	v, ok, err := codec.Decode(buf2)
   209  	assert.True(t, ok)
   210  	assert.Equal(t, msg.Message, v.(RPCMessage).Message)
   211  	assert.NoError(t, err)
   212  	assert.NotNil(t, v.(RPCMessage).Ctx)
   213  	assert.NotNil(t, v.(RPCMessage).cancel)
   214  }
   215  
   216  func TestEncodeAndDecodeWithEmptyPayloadAndChecksumMismatch(t *testing.T) {
   217  	ctx, cancel := context.WithTimeout(context.TODO(), time.Hour*10)
   218  	defer cancel()
   219  
   220  	codec := newTestCodec(WithCodecEnableChecksum())
   221  	buf1 := buf.NewByteBuf(32)
   222  	buf2 := buf.NewByteBuf(32)
   223  
   224  	msg := RPCMessage{Ctx: ctx, Message: newTestMessage(1)}
   225  	err := codec.Encode(msg, buf1, buf2)
   226  	assert.NoError(t, err)
   227  	io.Copy(buf2, buf1)
   228  
   229  	buf.Uint64ToBytesTo(0, buf2.RawSlice(5, 5+8))
   230  	_, ok, err := codec.Decode(buf2)
   231  	assert.False(t, ok)
   232  	assert.Error(t, err)
   233  }
   234  
   235  func TestNewWithMaxBodySize(t *testing.T) {
   236  	ctx, cancel := context.WithTimeout(context.TODO(), time.Hour*10)
   237  	defer cancel()
   238  
   239  	maxBodySize := 1024 * 1024 * 20
   240  	codec := newTestCodec(WithCodecMaxBodySize(maxBodySize + 1024))
   241  	buf1 := buf.NewByteBuf(32)
   242  	buf2 := buf.NewByteBuf(32)
   243  
   244  	msg := RPCMessage{Ctx: ctx, Message: newTestMessage(1)}
   245  	msg.Message.(*testMessage).payload = make([]byte, 1024*1024*11)
   246  	err := codec.Encode(msg, buf1, buf2)
   247  	assert.NoError(t, err)
   248  
   249  	v, ok, err := codec.Decode(buf2)
   250  	assert.True(t, ok)
   251  	assert.Equal(t, msg.Message, v.(RPCMessage).Message)
   252  	assert.NoError(t, err)
   253  	assert.NotNil(t, v.(RPCMessage).Ctx)
   254  	assert.NotNil(t, v.(RPCMessage).cancel)
   255  }
   256  
   257  func TestBufferScale(t *testing.T) {
   258  	stopper := stopper.NewStopper("")
   259  	defer stopper.Stop()
   260  
   261  	ctx, cancel := context.WithTimeout(context.TODO(), time.Hour*10)
   262  	defer cancel()
   263  	c1 := newTestCodec(WithCodecEnableChecksum(),
   264  		WithCodecIntegrationHLC(clock.NewUnixNanoHLCClockWithStopper(stopper, 0)),
   265  		WithCodecPayloadCopyBufferSize(16*1024))
   266  	c2 := newTestCodec(WithCodecEnableChecksum(),
   267  		WithCodecIntegrationHLC(clock.NewUnixNanoHLCClockWithStopper(stopper, 0)),
   268  		WithCodecPayloadCopyBufferSize(16*1024))
   269  	out := buf.NewByteBuf(32)
   270  	conn := buf.NewByteBuf(32)
   271  
   272  	n := 100
   273  	var messages []RPCMessage
   274  	for i := 0; i < n; i++ {
   275  		msg := RPCMessage{Ctx: ctx, Message: newTestMessage(uint64(i))}
   276  		payload := make([]byte, 1024*1024)
   277  		payload[len(payload)-1] = byte(i)
   278  		msg.Message.(*testMessage).payload = payload
   279  		messages = append(messages, msg)
   280  
   281  		require.NoError(t, c1.Encode(msg, out, conn))
   282  	}
   283  	_, err := out.WriteTo(conn)
   284  	if err != nil {
   285  		require.Equal(t, io.EOF, err)
   286  	}
   287  
   288  	for i := 0; i < n; i++ {
   289  		msg, ok, err := c2.Decode(conn)
   290  		require.NoError(t, err)
   291  		require.True(t, ok)
   292  		require.Equal(t, messages[i].Message, msg.(RPCMessage).Message)
   293  	}
   294  }
   295  
   296  func TestEncodeAndDecodeInternal(t *testing.T) {
   297  	codec := newTestCodec()
   298  	buf := buf.NewByteBuf(1)
   299  
   300  	ctx, cancel := context.WithTimeout(context.TODO(), time.Hour*10)
   301  	defer cancel()
   302  
   303  	msg := RPCMessage{Ctx: ctx, Message: &flagOnlyMessage{flag: flagPing}, internal: true}
   304  	err := codec.Encode(msg, buf, nil)
   305  	assert.NoError(t, err)
   306  
   307  	v, ok, err := codec.Decode(buf)
   308  	assert.True(t, ok)
   309  	assert.Equal(t, msg.Message, v.(RPCMessage).Message)
   310  	assert.NoError(t, err)
   311  	assert.NotNil(t, v.(RPCMessage).Ctx)
   312  	assert.NotNil(t, v.(RPCMessage).cancel)
   313  }