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  }