github.com/matrixorigin/matrixone@v1.2.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, 0)
    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  	// XXX Zhang Xu
   112  	//
   113  	// in codec, readMessage, dstPayload is freed c.pool.Free(dstPayload)
   114  	// but it is returned again in SetPayloadField
   115  	// We have to enable the NoFixed flag so that mpool Free does not
   116  	// really destroy the memory.
   117  	p, err := mpool.NewMPool("test", 0, mpool.NoFixed)
   118  	require.NoError(t, err)
   119  
   120  	ctx, cancel := context.WithTimeout(context.TODO(), time.Hour*10)
   121  	defer cancel()
   122  
   123  	codec := newTestCodec(WithCodecEnableCompress(p))
   124  	buf1 := buf.NewByteBuf(32)
   125  	buf2 := buf.NewByteBuf(32)
   126  
   127  	msg := RPCMessage{Ctx: ctx, Message: newTestMessage(1)}
   128  	msg.Message.(*testMessage).payload = []byte(strings.Repeat("payload", 100))
   129  	err = codec.Encode(msg, buf1, buf2)
   130  	assert.NoError(t, err)
   131  
   132  	v, ok, err := codec.Decode(buf2)
   133  	assert.True(t, ok)
   134  	assert.Equal(t, msg.Message, v.(RPCMessage).Message)
   135  	assert.NoError(t, err)
   136  	assert.NotNil(t, v.(RPCMessage).Ctx)
   137  	assert.NotNil(t, v.(RPCMessage).Cancel)
   138  }
   139  
   140  func TestEncodeAndDecodeAndChecksumMismatch(t *testing.T) {
   141  	ctx, cancel := context.WithTimeout(context.TODO(), time.Hour*10)
   142  	defer cancel()
   143  
   144  	codec := newTestCodec(WithCodecEnableChecksum())
   145  	buf1 := buf.NewByteBuf(32)
   146  
   147  	msg := RPCMessage{Ctx: ctx, Message: newTestMessage(1)}
   148  	err := codec.Encode(msg, buf1, nil)
   149  	assert.NoError(t, err)
   150  
   151  	buf.Uint64ToBytesTo(0, buf1.RawSlice(5, 5+8))
   152  
   153  	v, ok, err := codec.Decode(buf1)
   154  	assert.False(t, ok)
   155  	assert.Error(t, err)
   156  	assert.Nil(t, v)
   157  }
   158  
   159  func TestEncodeAndDecodeWithPayload(t *testing.T) {
   160  	ctx, cancel := context.WithTimeout(context.TODO(), time.Hour*10)
   161  	defer cancel()
   162  
   163  	codec := newTestCodec()
   164  	buf1 := buf.NewByteBuf(32)
   165  	buf2 := buf.NewByteBuf(32)
   166  
   167  	msg := RPCMessage{Ctx: ctx, Message: newTestMessage(1)}
   168  	msg.Message.(*testMessage).payload = []byte("payload")
   169  	err := codec.Encode(msg, buf1, buf2)
   170  	assert.NoError(t, err)
   171  
   172  	v, ok, err := codec.Decode(buf2)
   173  	assert.True(t, ok)
   174  	assert.Equal(t, msg.Message, v.(RPCMessage).Message)
   175  	assert.NoError(t, err)
   176  	assert.NotNil(t, v.(RPCMessage).Ctx)
   177  	assert.NotNil(t, v.(RPCMessage).Cancel)
   178  }
   179  
   180  func TestEncodeAndDecodeWithPayloadAndChecksum(t *testing.T) {
   181  	ctx, cancel := context.WithTimeout(context.TODO(), time.Hour*10)
   182  	defer cancel()
   183  
   184  	codec := newTestCodec(WithCodecEnableChecksum())
   185  	buf1 := buf.NewByteBuf(32)
   186  	buf2 := buf.NewByteBuf(32)
   187  
   188  	msg := RPCMessage{Ctx: ctx, Message: newTestMessage(1)}
   189  	msg.Message.(*testMessage).payload = []byte("payload")
   190  	err := codec.Encode(msg, buf1, buf2)
   191  	assert.NoError(t, err)
   192  
   193  	v, ok, err := codec.Decode(buf2)
   194  	assert.True(t, ok)
   195  	assert.Equal(t, msg.Message, v.(RPCMessage).Message)
   196  	assert.NoError(t, err)
   197  	assert.NotNil(t, v.(RPCMessage).Ctx)
   198  	assert.NotNil(t, v.(RPCMessage).Cancel)
   199  }
   200  
   201  func TestEncodeAndDecodeWithEmptyPayloadAndChecksum(t *testing.T) {
   202  	ctx, cancel := context.WithTimeout(context.TODO(), time.Hour*10)
   203  	defer cancel()
   204  
   205  	codec := newTestCodec(WithCodecEnableChecksum())
   206  	buf1 := buf.NewByteBuf(32)
   207  	buf2 := buf.NewByteBuf(32)
   208  
   209  	msg := RPCMessage{Ctx: ctx, Message: newTestMessage(1)}
   210  	err := codec.Encode(msg, buf1, buf2)
   211  	assert.NoError(t, err)
   212  	io.Copy(buf2, buf1)
   213  
   214  	v, ok, err := codec.Decode(buf2)
   215  	assert.True(t, ok)
   216  	assert.Equal(t, msg.Message, v.(RPCMessage).Message)
   217  	assert.NoError(t, err)
   218  	assert.NotNil(t, v.(RPCMessage).Ctx)
   219  	assert.NotNil(t, v.(RPCMessage).Cancel)
   220  }
   221  
   222  func TestEncodeAndDecodeWithEmptyPayloadAndChecksumMismatch(t *testing.T) {
   223  	ctx, cancel := context.WithTimeout(context.TODO(), time.Hour*10)
   224  	defer cancel()
   225  
   226  	codec := newTestCodec(WithCodecEnableChecksum())
   227  	buf1 := buf.NewByteBuf(32)
   228  	buf2 := buf.NewByteBuf(32)
   229  
   230  	msg := RPCMessage{Ctx: ctx, Message: newTestMessage(1)}
   231  	err := codec.Encode(msg, buf1, buf2)
   232  	assert.NoError(t, err)
   233  	io.Copy(buf2, buf1)
   234  
   235  	buf.Uint64ToBytesTo(0, buf2.RawSlice(5, 5+8))
   236  	_, ok, err := codec.Decode(buf2)
   237  	assert.False(t, ok)
   238  	assert.Error(t, err)
   239  }
   240  
   241  func TestNewWithMaxBodySize(t *testing.T) {
   242  	ctx, cancel := context.WithTimeout(context.TODO(), time.Hour*10)
   243  	defer cancel()
   244  
   245  	maxBodySize := 1024 * 1024 * 20
   246  	codec := newTestCodec(WithCodecMaxBodySize(maxBodySize + 1024))
   247  	buf1 := buf.NewByteBuf(32)
   248  	buf2 := buf.NewByteBuf(32)
   249  
   250  	msg := RPCMessage{Ctx: ctx, Message: newTestMessage(1)}
   251  	msg.Message.(*testMessage).payload = make([]byte, 1024*1024*11)
   252  	err := codec.Encode(msg, buf1, buf2)
   253  	assert.NoError(t, err)
   254  
   255  	v, ok, err := codec.Decode(buf2)
   256  	assert.True(t, ok)
   257  	assert.Equal(t, msg.Message, v.(RPCMessage).Message)
   258  	assert.NoError(t, err)
   259  	assert.NotNil(t, v.(RPCMessage).Ctx)
   260  	assert.NotNil(t, v.(RPCMessage).Cancel)
   261  }
   262  
   263  func TestBufferScale(t *testing.T) {
   264  	stopper := stopper.NewStopper("")
   265  	defer stopper.Stop()
   266  
   267  	ctx, cancel := context.WithTimeout(context.TODO(), time.Hour*10)
   268  	defer cancel()
   269  	c1 := newTestCodec(WithCodecEnableChecksum(),
   270  		WithCodecIntegrationHLC(clock.NewUnixNanoHLCClockWithStopper(stopper, 0)),
   271  		WithCodecPayloadCopyBufferSize(16*1024))
   272  	c2 := newTestCodec(WithCodecEnableChecksum(),
   273  		WithCodecIntegrationHLC(clock.NewUnixNanoHLCClockWithStopper(stopper, 0)),
   274  		WithCodecPayloadCopyBufferSize(16*1024))
   275  	out := buf.NewByteBuf(32)
   276  	conn := buf.NewByteBuf(32)
   277  
   278  	n := 100
   279  	var messages []RPCMessage
   280  	for i := 0; i < n; i++ {
   281  		msg := RPCMessage{Ctx: ctx, Message: newTestMessage(uint64(i))}
   282  		payload := make([]byte, 1024*1024)
   283  		payload[len(payload)-1] = byte(i)
   284  		msg.Message.(*testMessage).payload = payload
   285  		messages = append(messages, msg)
   286  
   287  		require.NoError(t, c1.Encode(msg, out, conn))
   288  	}
   289  	_, err := out.WriteTo(conn)
   290  	if err != nil {
   291  		require.Equal(t, io.EOF, err)
   292  	}
   293  
   294  	for i := 0; i < n; i++ {
   295  		msg, ok, err := c2.Decode(conn)
   296  		require.NoError(t, err)
   297  		require.True(t, ok)
   298  		require.Equal(t, messages[i].Message, msg.(RPCMessage).Message)
   299  	}
   300  }
   301  
   302  func TestEncodeAndDecodeInternal(t *testing.T) {
   303  	codec := newTestCodec()
   304  	buf := buf.NewByteBuf(1)
   305  
   306  	ctx, cancel := context.WithTimeout(context.TODO(), time.Hour*10)
   307  	defer cancel()
   308  
   309  	msg := RPCMessage{Ctx: ctx, Message: &flagOnlyMessage{flag: flagPing}, internal: true}
   310  	err := codec.Encode(msg, buf, nil)
   311  	assert.NoError(t, err)
   312  
   313  	v, ok, err := codec.Decode(buf)
   314  	assert.True(t, ok)
   315  	assert.Equal(t, msg.Message, v.(RPCMessage).Message)
   316  	assert.NoError(t, err)
   317  	assert.NotNil(t, v.(RPCMessage).Ctx)
   318  	assert.NotNil(t, v.(RPCMessage).Cancel)
   319  }