github.com/nyan233/littlerpc@v0.4.6-0.20230316182519-0c8d5c48abaf/test/feature_test.go (about) 1 package main 2 3 import ( 4 "context" 5 "fmt" 6 "github.com/nyan233/littlerpc/core/client" 7 "github.com/nyan233/littlerpc/core/common/logger" 8 "github.com/nyan233/littlerpc/core/common/metadata" 9 server2 "github.com/nyan233/littlerpc/core/server" 10 "github.com/nyan233/littlerpc/plugins/metrics" 11 "github.com/stretchr/testify/assert" 12 "github.com/zbh255/bilog" 13 "log" 14 "net/http" 15 _ "net/http/pprof" 16 "os" 17 "sync" 18 "sync/atomic" 19 "testing" 20 "time" 21 ) 22 23 type User struct { 24 Id int 25 Name string 26 } 27 28 func (u *User) Reset() { 29 u.Id = 0 30 u.Name = "" 31 } 32 33 type HelloTest struct { 34 count int64 35 // 社区旗下的一些用户 36 userMap sync.Map 37 t *testing.T 38 server2.RpcServer 39 } 40 41 func (t *HelloTest) Setup() { 42 err := t.HijackProcess("GetCount", func(stub *server2.Stub) { 43 assert.NoError(t.t, stub.Write(atomic.LoadInt64(&t.count))) 44 assert.NoError(t.t, stub.Write(nil)) 45 assert.NoError(t.t, stub.WriteErr(nil)) 46 }) 47 assert.NoError(t.t, err) 48 err = t.HijackProcess("WaitSelectUserHijack", func(stub *server2.Stub) { 49 var uid int 50 assert.NoError(t.t, stub.Read(&uid)) 51 // wait 52 <-stub.Done() 53 user, _, err := t.SelectUser(stub, uid) 54 assert.NoError(t.t, stub.Write(&user)) 55 assert.NoError(t.t, stub.WriteErr(err)) 56 }) 57 assert.NoError(t.t, err) 58 } 59 60 func (t *HelloTest) GetCount() (int64, *User, error) { 61 return atomic.LoadInt64(&t.count), nil, nil 62 } 63 64 func (t *HelloTest) Add(i int64) error { 65 atomic.AddInt64(&t.count, i) 66 return nil 67 } 68 69 func (t *HelloTest) CreateUser(ctx context.Context, user *User) error { 70 t.userMap.Store(user.Id, *user) 71 return nil 72 } 73 74 func (t *HelloTest) DeleteUser(ctx context.Context, uid int) error { 75 t.userMap.Delete(uid) 76 return nil 77 } 78 79 func (t *HelloTest) SelectUser(ctx context.Context, uid int) (User, bool, error) { 80 u, ok := t.userMap.Load(uid) 81 if ok { 82 return u.(User), ok, nil 83 } 84 return User{}, false, nil 85 } 86 87 func (t *HelloTest) ModifyUser(ctx context.Context, uid int, user User) (bool, error) { 88 _, ok := t.userMap.LoadOrStore(uid, user) 89 return ok, nil 90 } 91 92 func (t *HelloTest) WaitSelectUser(ctx context.Context, uid int) (*User, error) { 93 <-ctx.Done() 94 user, _, err := t.SelectUser(ctx, uid) 95 return &user, err 96 } 97 98 func (t *HelloTest) WaitSelectUserHijack(ctx context.Context, uid int) (*User, error) { 99 return nil, nil 100 } 101 102 func TestServerAndClient(t *testing.T) { 103 go func() { 104 log.Println(http.ListenAndServe("127.0.0.1:7878", nil)) 105 }() 106 // 关闭服务器烦人的日志 107 logger.SetOpenLogger(false) 108 baseServerOpts := []server2.Option{ 109 server2.WithAddressServer(":1234"), 110 server2.WithStackTrace(), 111 server2.WithLogger(logger.New(bilog.NewLogger(os.Stdout, bilog.PANIC, 112 bilog.WithLowBuffer(0), bilog.WithTopBuffer(0)))), 113 server2.WithOpenLogger(false), 114 server2.WithDebug(false), 115 // server2.WithMessageParserOnRead(), 116 // server2.WithPlugin(pLogger.New(os.Stdout)), 117 } 118 baseClientOpts := []client.Option{ 119 client.WithAddress(":1234"), 120 client.WithMuxConnectionNumber(16), 121 client.WithStackTrace(), 122 } 123 testRunConfigs := []struct { 124 TestName string 125 NoAbleUsageNoTransactionProtocol bool 126 ServerOptions []server2.Option 127 ClientOptions []client.Option 128 CallOptions map[string][]client.CallOption 129 }{ 130 { 131 TestName: "TestLRPCProtocol-%s-NoMux-NonTls", 132 ServerOptions: append(baseServerOpts), 133 ClientOptions: append(baseClientOpts, client.WithNoMuxWriter()), 134 CallOptions: map[string][]client.CallOption{ 135 "SelectUser": { 136 client.WithCallLRPCMuxWriter(), 137 client.WithCallPacker("gzip"), 138 }, 139 }, 140 }, 141 { 142 TestName: "TestLRPCProtocol-%s-Mux-NonTls", 143 ServerOptions: append(baseServerOpts), 144 ClientOptions: append(baseClientOpts, client.WithMuxWriter()), 145 CallOptions: map[string][]client.CallOption{ 146 "SelectUser": { 147 client.WithCallLRPCNoMuxWriter(), 148 client.WithCallPacker("gzip"), 149 }, 150 }, 151 }, 152 { 153 TestName: "TestLRPCProtocol-%s-NoMux-Gzip-NonTls", 154 ServerOptions: append(baseServerOpts), 155 ClientOptions: append(baseClientOpts, client.WithNoMuxWriter(), client.WithPacker("gzip")), 156 }, 157 { 158 TestName: "TestLRPCProtocol-%s-Mux-Gzip-NonTls", 159 ServerOptions: append(baseServerOpts), 160 ClientOptions: append(baseClientOpts, client.WithMuxWriter(), client.WithPacker("gzip")), 161 }, 162 { 163 TestName: "TestJsonRPC2-%s-SingleProtocol-NonTls", 164 ServerOptions: append(baseServerOpts), 165 ClientOptions: append(baseClientOpts, client.WithJsonRpc2Writer()), 166 NoAbleUsageNoTransactionProtocol: true, 167 }, 168 } 169 networks := []string{"nbio_tcp", "std_tcp", "nbio_ws"} 170 for _, network := range networks { 171 for _, runConfig := range testRunConfigs { 172 if runConfig.NoAbleUsageNoTransactionProtocol { 173 switch network { 174 case "nbio_tcp": 175 continue 176 case "std_tcp": 177 continue 178 } 179 } 180 t.Run(fmt.Sprintf(runConfig.TestName, network), func(t *testing.T) { 181 testServerAndClient(t, 182 append([]server2.Option{server2.WithNetwork(network)}, runConfig.ServerOptions...), 183 append([]client.Option{client.WithNetWork(network)}, runConfig.ClientOptions...), 184 runConfig.CallOptions) 185 }) 186 } 187 } 188 } 189 190 func testServerAndClient(t *testing.T, serverOpts []server2.Option, clientOpts []client.Option, 191 ccSet map[string][]client.CallOption) { 192 sm := metrics.NewServer() 193 server := server2.New(append(serverOpts, server2.WithPlugin(sm))...) 194 h := &HelloTest{ 195 t: t, 196 } 197 err := server.RegisterClass("", h, map[string]metadata.ProcessOption{ 198 "SelectUser": { 199 SyncCall: true, 200 CompleteReUsage: true, 201 }, 202 "CreateUser": { 203 SyncCall: true, 204 CompleteReUsage: true, 205 }, 206 "Add": { 207 SyncCall: true, 208 CompleteReUsage: true, 209 }, 210 "WaitSelectUser": { 211 CompleteReUsage: false, 212 UseRawGoroutine: true, 213 }, 214 }) 215 assert.NoError(t, err, "server register class failed") 216 go server.Service() 217 218 defer server.Stop() 219 220 var wg sync.WaitGroup 221 // 启动多少的客户端 222 nGoroutine := 50 223 // 一个客户端连续发送多少次消息 224 sendN := 50 225 addV := 65536 226 wg.Add(nGoroutine) 227 cm := metrics.NewClient() 228 c, err := client.New(append(clientOpts, client.WithPlugin(cm))...) 229 assert.NoError(t, err, "client start failed") 230 proxy := NewHelloTest(c) 231 for i := 0; i < nGoroutine; i++ { 232 j := i 233 go func() { 234 for k := 0; k < sendN; k++ { 235 assert.NoError(t, proxy.Add(int64(addV)), "add failed") 236 var opts []client.CallOption 237 opts, _ = ccSet["CreateUser"] 238 assert.NoError(t, proxy.CreateUser(context.Background(), &User{ 239 Id: j + 100, 240 Name: "Jeni", 241 }, opts...), "create user failed") 242 opts, _ = ccSet["SelectUser"] 243 user, _, err := proxy.SelectUser(context.Background(), j+100, opts...) 244 assert.NoError(t, err, "select user failed") 245 assert.Equal(t, user.Name, "Jeni", "the no value") 246 opts, _ = ccSet["ModifyUser"] 247 _, err = proxy.ModifyUser(context.Background(), j+100, User{ 248 Id: j + 100, 249 Name: "Tony", 250 }, opts...) 251 assert.NoError(t, err, "modify user failed") 252 opts, _ = ccSet["GetCount"] 253 _, _, err = proxy.GetCount(opts...) 254 assert.NoError(t, err, "get count failed") 255 opts, _ = ccSet["DeleteUser"] 256 assert.NoError(t, proxy.DeleteUser(context.Background(), j+100, opts...), "delete user failed") 257 // 构造一次错误的请求 258 _, err = c.Call("HelloTest.DeleteUser", nil, context.Background(), "string") 259 assert.Error(t, err, "call error is equal nil") 260 // 构造一次取消的请求 261 ctx, _ := context.WithTimeout(context.Background(), time.Millisecond) 262 var rep User 263 opts, _ = ccSet["WaitSelectUser"] 264 assert.NoError(t, c.Request("HelloTest.WaitSelectUser", ctx, j+100, &rep, opts...), "cancel request failed") 265 // test hijack context 266 ctx, _ = context.WithTimeout(context.Background(), time.Millisecond) 267 _, err = proxy.WaitSelectUserHijack(ctx, 10) 268 assert.NoError(t, err, "cancel request failed") 269 } 270 wg.Done() 271 }() 272 } 273 wg.Wait() 274 assert.Equal(t, atomic.LoadInt64(&h.count), int64(addV*nGoroutine)*int64(sendN), "h.count no correct") 275 276 assert.Equal(t, cm.Call.LoadFailed(), sm.Call.LoadFailed()) 277 //assert.Equal(t, cm.Call.LoadComplete(), sm.Call.LoadComplete()) 278 //assert.Equal(t, cm.Call.LoadAll(), sm.Call.LoadAll()) 279 //assert.Equal(t, cm.Call.LoadCount(), sm.Call.LoadCount()) 280 281 assert.Equal(t, cm.Call.LoadFailed(), int64(nGoroutine)*int64(sendN), "errCount size not correct") 282 } 283 284 func TestBalance(t *testing.T) { 285 // 关闭服务器烦人的日志 286 logger.SetOpenLogger(false) 287 server := server2.New(server2.WithAddressServer("127.0.0.1:9090", "127.0.0.1:8080"), 288 server2.WithOpenLogger(false)) 289 err := server.RegisterClass("", new(HelloTest), nil) 290 if err != nil { 291 t.Fatal(err) 292 } 293 go server.Service() 294 time.Sleep(time.Second) 295 defer server.Stop() 296 c1, err := client.New( 297 client.WithBalancerScheme("roundRobin"), 298 client.WithOpenLoadBalance(), 299 client.WithLiveResolver("127.0.0.1:8080;127.0.0.1:9090"), 300 ) 301 if err != nil { 302 t.Fatal(err) 303 } 304 p1 := NewHelloTest(c1) 305 c2, err := client.New( 306 client.WithBalancerScheme("roundRobin"), 307 client.WithOpenLoadBalance(), 308 client.WithLiveResolver("127.0.0.1:8080;127.0.0.1:9090"), 309 ) 310 if err != nil { 311 t.Fatal(err) 312 } 313 p2 := NewHelloTest(c2) 314 p1.Add(1024) 315 p2.Add(1023) 316 }