github.com/turingchain2020/turingchain@v1.1.21/queue/queue_test.go (about) 1 // Copyright Turing Corp. 2018 All Rights Reserved. 2 // Use of this source code is governed by a BSD-style 3 // license that can be found in the LICENSE file. 4 5 package queue 6 7 import ( 8 "fmt" 9 "testing" 10 "time" 11 12 "github.com/turingchain2020/turingchain/types" 13 "github.com/stretchr/testify/assert" 14 ) 15 16 func init() { 17 DisableLog() 18 } 19 20 func TestTimeout(t *testing.T) { 21 //send timeout and recv timeout 22 q := New("channel") 23 24 //mempool 25 go func() { 26 client := q.Client() 27 client.Sub("mempool") 28 for msg := range client.Recv() { 29 if msg.Ty == types.EventTx { 30 time.Sleep(time.Second) 31 msg.Reply(client.NewMessage("mempool", types.EventReply, types.Reply{IsOk: true, Msg: []byte("word")})) 32 } 33 } 34 }() 35 client := q.Client() 36 //rpc 模块 会向其他模块发送消息,自己本身不需要订阅消息 37 msg := client.NewMessage("blockchain", types.EventTx, "hello") 38 for i := 0; i < defaultChanBuffer; i++ { 39 err := client.SendTimeout(msg, true, 0) 40 if err != nil { 41 t.Error(err) 42 return 43 } 44 } 45 46 //再发送一个交易返回chain full 47 err := client.SendTimeout(msg, true, 0) 48 if err != ErrQueueChannelFull { 49 t.Error(err) 50 return 51 } 52 53 //发送一个交易返回返回timeout 54 err = client.SendTimeout(msg, true, time.Millisecond) 55 if err != ErrQueueTimeout { 56 t.Error(err) 57 return 58 } 59 } 60 61 func TestClient_WaitTimeout(t *testing.T) { 62 q := New("channel") 63 client := q.Client() 64 msg := client.NewMessage("mempool", types.EventTx, "hello") 65 err := client.SendTimeout(msg, true, 0) 66 if err != nil { 67 t.Error(err) 68 return 69 } 70 71 _, err = client.WaitTimeout(msg, time.Second*5) 72 assert.Equal(t, ErrQueueTimeout, err) 73 74 } 75 76 func TestMultiTopic(t *testing.T) { 77 q := New("channel") 78 79 //mempool 80 go func() { 81 client := q.Client() 82 client.Sub("mempool") 83 for msg := range client.Recv() { 84 if msg.Ty == types.EventTx { 85 msg.Reply(client.NewMessage("mempool", types.EventReply, types.Reply{IsOk: true, Msg: []byte("word")})) 86 } 87 } 88 }() 89 90 //blockchain 91 go func() { 92 client := q.Client() 93 client.Sub("blockchain") 94 for msg := range client.Recv() { 95 if msg.Ty == types.EventGetBlockHeight { 96 msg.Reply(client.NewMessage("blockchain", types.EventReplyBlockHeight, types.ReplyBlockHeight{Height: 100})) 97 } 98 } 99 }() 100 101 //rpc server 102 go func() { 103 client := q.Client() 104 //rpc 模块 会向其他模块发送消息,自己本身不需要订阅消息 105 msg := client.NewMessage("mempool", types.EventTx, "hello") 106 client.Send(msg, true) 107 reply, err := client.Wait(msg) 108 if err != nil { 109 t.Error(err) 110 return 111 } 112 t.Log(string(reply.GetData().(types.Reply).Msg)) 113 114 msg = client.NewMessage("blockchain", types.EventGetBlockHeight, nil) 115 client.Send(msg, true) 116 reply, err = client.Wait(msg) 117 if err != nil { 118 t.Error(err) 119 return 120 } 121 t.Log(reply) 122 q.Close() 123 }() 124 q.Start() 125 } 126 127 //发送100000 低优先级的消息,然后发送一个高优先级的消息 128 //高优先级的消息可以即时返回 129 func TestHighLow(t *testing.T) { 130 q := New("channel") 131 132 //mempool 133 go func() { 134 client := q.Client() 135 client.Sub("mempool") 136 for msg := range client.Recv() { 137 if msg.Ty == types.EventTx { 138 time.Sleep(time.Second) 139 msg.Reply(client.NewMessage("mempool", types.EventReply, types.Reply{IsOk: true, Msg: []byte("word")})) 140 } 141 } 142 }() 143 144 //rpc server 145 go func() { 146 client := q.Client() 147 //rpc 模块 会向其他模块发送消息,自己本身不需要订阅消息 148 for { 149 msg := client.NewMessage("mempool", types.EventTx, "hello") 150 err := client.SendTimeout(msg, false, 0) 151 if err != nil { 152 fmt.Println(err) 153 break 154 } 155 } 156 //high 优先级 157 msg := client.NewMessage("mempool", types.EventTx, "hello") 158 client.Send(msg, true) 159 reply, err := client.Wait(msg) 160 if err != nil { 161 t.Error(err) 162 return 163 } 164 t.Log(string(reply.GetData().(types.Reply).Msg)) 165 q.Close() 166 }() 167 q.Start() 168 } 169 170 //发送100000 低优先级的消息,然后发送一个高优先级的消息 171 //高优先级的消息可以即时返回 172 func TestClientClose(t *testing.T) { 173 q := New("channel") 174 //mempool 175 go func() { 176 client := q.Client() 177 client.Sub("mempool") 178 i := 0 179 for msg := range client.Recv() { 180 if msg.Ty == types.EventTx { 181 time.Sleep(time.Second / 10) 182 msg.Reply(client.NewMessage("mempool", types.EventReply, types.Reply{IsOk: true, Msg: []byte("word")})) 183 } 184 i++ 185 if i == 10 { 186 go func() { 187 client.Close() 188 qlog.Info("close ok") 189 }() 190 } 191 } 192 }() 193 194 //rpc server 195 go func() { 196 client := q.Client() 197 //high 优先级 198 done := make(chan struct{}, 100) 199 for i := 0; i < 100; i++ { 200 go func() { 201 defer func() { 202 done <- struct{}{} 203 }() 204 msg := client.NewMessage("mempool", types.EventTx, "hello") 205 err := client.Send(msg, true) 206 if err == types.ErrChannelClosed { 207 return 208 } 209 if err != nil { //chan is closed 210 t.Error(err) 211 return 212 } 213 _, err = client.Wait(msg) 214 if err == types.ErrChannelClosed { 215 return 216 } 217 if err != nil { 218 t.Error(err) 219 return 220 } 221 }() 222 } 223 for i := 0; i < 100; i++ { 224 <-done 225 } 226 q.Close() 227 }() 228 q.Start() 229 } 230 231 func TestPrintMessage(t *testing.T) { 232 q := New("channel") 233 client := q.Client() 234 msg := client.NewMessage("mempool", types.EventReply, types.Reply{IsOk: true, Msg: []byte("word")}) 235 t.Log(msg) 236 } 237 238 func TestMessage_ReplyErr(t *testing.T) { 239 q := New("channel") 240 assert.Equal(t, "channel", q.Name()) 241 //接收消息 242 go func() { 243 client := q.Client() 244 client.Sub("mempool") 245 for msg := range client.Recv() { 246 if msg.Data == nil { 247 msg.ReplyErr("test", fmt.Errorf("test error")) 248 break 249 } 250 msg.Reply(NewMessage(0, "mempool", types.EventReply, types.Reply{IsOk: true, Msg: []byte("test ok")})) 251 } 252 }() 253 254 //发送消息 255 go func() { 256 client := q.Client() 257 msg := client.NewMessage("mempool", types.EventTx, "hello") 258 err := client.Send(msg, true) 259 if err != nil { //chan is closed 260 t.Error(err) 261 return 262 } 263 264 msg = client.NewMessage("mempool", types.EventTx, nil) 265 err = client.Send(msg, true) 266 if err != nil { 267 t.Error(err) 268 return 269 } 270 client.CloseQueue() 271 }() 272 273 q.Start() 274 } 275 276 func TestChanSubCallback(t *testing.T) { 277 q := New("channel") 278 client := q.Client() 279 client.Sub("hello") 280 done := make(chan struct{}, 1025) 281 go func() { 282 for i := 0; i < 1025; i++ { 283 sub := q.(*queue).chanSub("hello") 284 msg := NewMessageCallback(1, "", 0, nil, func(msg *Message) { 285 done <- struct{}{} 286 }) 287 sub.high <- msg 288 } 289 }() 290 for i := 0; i < 1025; i++ { 291 msg := <-client.Recv() 292 client.Reply(msg) 293 } 294 for i := 0; i < 1025; i++ { 295 <-done 296 } 297 } 298 299 func BenchmarkSendMessage(b *testing.B) { 300 q := New("channel") 301 //mempool 302 b.ReportAllocs() 303 go func() { 304 client := q.Client() 305 client.Sub("mempool") 306 defer client.Close() 307 for msg := range client.Recv() { 308 go func(msg *Message) { 309 if msg.Ty == types.EventTx { 310 msg.Reply(client.NewMessage("mempool", types.EventReply, types.Reply{IsOk: true, Msg: []byte("word")})) 311 } 312 }(msg) 313 } 314 }() 315 go q.Start() 316 client := q.Client() 317 //high 优先级 318 msg := client.NewMessage("mempool", types.EventTx, "hello") 319 for i := 0; i < b.N; i++ { 320 err := client.Send(msg, true) 321 if err != nil { 322 b.Error(err) 323 return 324 } 325 _, err = client.Wait(msg) 326 if err != nil { 327 b.Error(err) 328 return 329 } 330 } 331 } 332 333 func BenchmarkStructChan(b *testing.B) { 334 ch := make(chan struct{}) 335 go func() { 336 for { 337 <-ch 338 } 339 }() 340 for i := 0; i < b.N; i++ { 341 ch <- struct{}{} 342 } 343 } 344 345 func BenchmarkBoolChan(b *testing.B) { 346 ch := make(chan bool) 347 go func() { 348 for { 349 <-ch 350 } 351 }() 352 for i := 0; i < b.N; i++ { 353 ch <- true 354 } 355 } 356 357 func BenchmarkIntChan(b *testing.B) { 358 ch := make(chan int) 359 go func() { 360 for { 361 <-ch 362 } 363 }() 364 for i := 0; i < b.N; i++ { 365 ch <- 1 366 } 367 } 368 369 func BenchmarkChanSub(b *testing.B) { 370 q := New("channel") 371 done := make(chan struct{}) 372 go func() { 373 for i := 0; i < b.N; i++ { 374 q.(*queue).chanSub("hello") 375 } 376 done <- struct{}{} 377 }() 378 for i := 0; i < b.N; i++ { 379 q.(*queue).chanSub("hello") 380 } 381 <-done 382 } 383 384 func BenchmarkChanSub2(b *testing.B) { 385 q := New("channel") 386 client := q.Client() 387 client.Sub("hello") 388 389 go func() { 390 for i := 0; i < b.N; i++ { 391 sub := q.(*queue).chanSub("hello") 392 msg := NewMessage(1, "", 0, nil) 393 sub.high <- msg 394 _, err := client.Wait(msg) 395 if err != nil { 396 b.Fatal(err) 397 } 398 } 399 }() 400 for i := 0; i < b.N; i++ { 401 msg := <-client.Recv() 402 msg.Reply(msg) 403 } 404 } 405 406 func BenchmarkChanSub3(b *testing.B) { 407 q := New("channel") 408 client := q.Client() 409 client.Sub("hello") 410 411 go func() { 412 for i := 0; i < b.N; i++ { 413 sub := q.(*queue).chanSub("hello") 414 msg := NewMessage(1, "", 0, nil) 415 sub.high <- msg 416 } 417 }() 418 for i := 0; i < b.N; i++ { 419 msg := <-client.Recv() 420 msg.Reply(msg) 421 } 422 } 423 424 func BenchmarkChanSub4(b *testing.B) { 425 q := New("channel") 426 client := q.Client() 427 client.Sub("hello") 428 429 go func() { 430 for i := 0; i < b.N; i++ { 431 sub := q.(*queue).chanSub("hello") 432 msg := &Message{ID: 1} 433 sub.high <- msg 434 } 435 }() 436 for i := 0; i < b.N; i++ { 437 <-client.Recv() 438 } 439 } 440 441 func BenchmarkChanSubCallback(b *testing.B) { 442 q := New("channel") 443 client := q.Client() 444 client.Sub("hello") 445 done := make(chan struct{}, 1024) 446 go func() { 447 for i := 0; i < b.N; i++ { 448 sub := q.(*queue).chanSub("hello") 449 msg := NewMessageCallback(1, "", 0, nil, func(msg *Message) { 450 done <- struct{}{} 451 }) 452 sub.high <- msg 453 } 454 }() 455 go func() { 456 for i := 0; i < b.N; i++ { 457 msg := <-client.Recv() 458 client.Reply(msg) 459 } 460 }() 461 for i := 0; i < b.N; i++ { 462 <-done 463 } 464 } 465 466 func BenchmarkChanSubCallback2(b *testing.B) { 467 q := New("channel") 468 client := q.Client() 469 client.Sub("hello") 470 go func() { 471 for i := 0; i < b.N; i++ { 472 sub := q.(*queue).chanSub("hello") 473 done := make(chan struct{}, 1) 474 msg := NewMessageCallback(1, "", 0, nil, func(msg *Message) { 475 done <- struct{}{} 476 }) 477 sub.high <- msg 478 <-done 479 } 480 }() 481 for i := 0; i < b.N; i++ { 482 msg := <-client.Recv() 483 client.Reply(msg) 484 } 485 } 486 487 func TestChannelClose(t *testing.T) { 488 //send timeout and recv timeout 489 q := New("channel") 490 491 //mempool 492 done := make(chan struct{}, 1) 493 go func() { 494 client := q.Client() 495 client.Sub("mempool") 496 for { 497 select { 498 case msg := <-client.Recv(): 499 if msg == nil { 500 return 501 } 502 if msg.Ty == types.EventTx { 503 msg.Reply(client.NewMessage("mempool", types.EventReply, types.Reply{IsOk: true, Msg: []byte("word")})) 504 } 505 case <-done: 506 client.Close() 507 return 508 } 509 } 510 }() 511 client := q.Client() 512 go q.Start() 513 //rpc 模块 会向其他模块发送消息,自己本身不需要订阅消息 514 go func() { 515 done <- struct{}{} 516 }() 517 for i := 0; i < 10000; i++ { 518 msg := client.NewMessage("mempool", types.EventTx, "hello") 519 err := client.SendTimeout(msg, true, 0) 520 if err == types.ErrChannelClosed { 521 return 522 } 523 if err != nil { 524 t.Error(err) 525 return 526 } 527 _, err = client.Wait(msg) 528 if err == types.ErrChannelClosed { 529 return 530 } 531 if err != nil { 532 t.Error(err) 533 } 534 } 535 }