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 }