github.com/igggame/nebulas-go@v2.1.0+incompatible/core/event_test.go (about)

     1  // Copyright (C) 2017 go-nebulas authors
     2  //
     3  // This file is part of the go-nebulas library.
     4  //
     5  // the go-nebulas library is free software: you can redistribute it and/or modify
     6  // it under the terms of the GNU General Public License as published by
     7  // the Free Software Foundation, either version 3 of the License, or
     8  // (at your option) any later version.
     9  //
    10  // the go-nebulas library is distributed in the hope that it will be useful,
    11  // but WITHOUT ANY WARRANTY; without even the implied warranty of
    12  // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    13  // GNU General Public License for more details.
    14  //
    15  // You should have received a copy of the GNU General Public License
    16  // along with the go-nebulas library.  If not, see <http://www.gnu.org/licenses/>.
    17  //
    18  
    19  package core
    20  
    21  import (
    22  	"fmt"
    23  	"math/rand"
    24  	"sync"
    25  	"testing"
    26  	"time"
    27  
    28  	"github.com/nebulasio/go-nebulas/core/state"
    29  
    30  	"github.com/stretchr/testify/assert"
    31  )
    32  
    33  func register(emitter *EventEmitter, topic string) *EventSubscriber {
    34  	eventSub := NewEventSubscriber(128, []string{topic})
    35  	emitter.Register(eventSub)
    36  	return eventSub
    37  }
    38  
    39  func TestEventEmitter(t *testing.T) {
    40  	// create emitter.
    41  	emitter := NewEventEmitter(1024)
    42  	emitter.Start()
    43  
    44  	// topic & categories
    45  	topics := []string{"chain.topic.01", "chain.topic.02", "chain.topic.03", "node.topic.11", "node.topic.12"}
    46  
    47  	// prepare chan.
    48  	t1ch := register(emitter, topics[0])
    49  	t2ch := register(emitter, topics[1])
    50  	t3ch := register(emitter, topics[2])
    51  
    52  	wg := new(sync.WaitGroup)
    53  	wg.Add(2)
    54  
    55  	totalEventCount := 1000
    56  	eventCountDist := make(map[string]int)
    57  	go func() {
    58  		// send message.
    59  		defer wg.Done()
    60  		rand.Seed(time.Now().UnixNano())
    61  
    62  		for i := 0; i < totalEventCount; i++ {
    63  
    64  			topic := topics[rand.Intn(len(topics))]
    65  
    66  			eventCountDist[topic] = eventCountDist[topic] + 1
    67  
    68  			e := &state.Event{
    69  				Topic: topic,
    70  				Data:  fmt.Sprintf("%d", i),
    71  			}
    72  			emitter.Trigger(e)
    73  		}
    74  	}()
    75  
    76  	t1c, t2c, t3c := 0, 0, 0
    77  	for len(t1ch.eventCh) > 0 {
    78  		e := <-t1ch.eventCh
    79  		assert.Equal(t, topics[0], e.Topic)
    80  		t1c++
    81  	}
    82  	for len(t2ch.eventCh) > 0 {
    83  		e := <-t2ch.eventCh
    84  		assert.Equal(t, topics[1], e.Topic)
    85  		t2c++
    86  	}
    87  	for len(t3ch.eventCh) > 0 {
    88  		e := <-t3ch.eventCh
    89  		assert.Equal(t, topics[2], e.Topic)
    90  		t3c++
    91  	}
    92  
    93  	at1c, at2c, at3c := eventCountDist[topics[0]], eventCountDist[topics[1]], eventCountDist[topics[2]]
    94  	assert.Equal(t, at1c, t1c)
    95  	assert.Equal(t, at2c, t2c)
    96  	assert.Equal(t, at3c, t3c)
    97  
    98  	emitter.Stop()
    99  	time.Sleep(time.Second)
   100  }
   101  
   102  func TestEventEmitterWithRunningRegDereg(t *testing.T) {
   103  	// create emitter.
   104  	emitter := NewEventEmitter(1024)
   105  	emitter.Start()
   106  
   107  	// topic
   108  	topics := []string{"chain.topic.01", "chain.topic.02", "node.topic.11"}
   109  
   110  	wg := new(sync.WaitGroup)
   111  	wg.Add(2)
   112  
   113  	totalEventCount := 1000
   114  	eventCountDist := make(map[string]int)
   115  
   116  	// prepare chan.
   117  	t1ch := register(emitter, topics[0])
   118  	t2ch := register(emitter, topics[1])
   119  	t3ch := register(emitter, topics[2])
   120  
   121  	go func() {
   122  		// send message.
   123  		defer wg.Done()
   124  		rand.Seed(time.Now().UnixNano())
   125  
   126  		for i := 0; i < totalEventCount; i++ {
   127  			if i%100 == 99 {
   128  				time.Sleep(time.Millisecond * 500)
   129  			}
   130  
   131  			topic := topics[rand.Intn(len(topics))]
   132  
   133  			eventCountDist[topic] = eventCountDist[topic] + 1
   134  
   135  			e := &state.Event{
   136  				Topic: topic,
   137  				Data:  fmt.Sprintf("%d", i),
   138  			}
   139  			emitter.Trigger(e)
   140  		}
   141  	}()
   142  
   143  	t1c, t2c, t3c := 0, 0, 0
   144  	go func() {
   145  		defer wg.Done()
   146  
   147  		for {
   148  			select {
   149  			case <-time.After(time.Second * 1):
   150  				return
   151  			case e := <-t1ch.eventCh:
   152  				assert.Equal(t, topics[0], e.Topic)
   153  				t1c++
   154  
   155  				if t1c%13 == 2 {
   156  					emitter.Deregister(t2ch)
   157  				} else if t1c%13 == 9 {
   158  					emitter.Register(t2ch)
   159  				}
   160  
   161  			case e := <-t2ch.eventCh:
   162  				assert.Equal(t, topics[1], e.Topic)
   163  				t2c++
   164  
   165  				if t2c%13 == 4 {
   166  					emitter.Deregister(t3ch)
   167  				} else if t2c%13 == 12 {
   168  					emitter.Register(t3ch)
   169  				}
   170  
   171  			case e := <-t3ch.eventCh:
   172  				assert.Equal(t, topics[2], e.Topic)
   173  				t3c++
   174  			}
   175  		}
   176  	}()
   177  
   178  	wg.Wait()
   179  
   180  	emitter.Stop()
   181  	time.Sleep(time.Millisecond * 100)
   182  }