github.com/neatlab/neatio@v1.7.3-0.20220425043230-d903e92fcc75/utilities/event/event_test.go (about)

     1  package event
     2  
     3  import (
     4  	"math/rand"
     5  	"sync"
     6  	"testing"
     7  	"time"
     8  )
     9  
    10  type testEvent int
    11  
    12  func TestSubCloseUnsub(t *testing.T) {
    13  
    14  	var mux TypeMux
    15  	mux.Stop()
    16  	sub := mux.Subscribe(int(0))
    17  	sub.Unsubscribe()
    18  }
    19  
    20  func TestSub(t *testing.T) {
    21  	mux := new(TypeMux)
    22  	defer mux.Stop()
    23  
    24  	sub := mux.Subscribe(testEvent(0))
    25  	go func() {
    26  		if err := mux.Post(testEvent(5)); err != nil {
    27  			t.Errorf("Post returned unexpected error: %v", err)
    28  		}
    29  	}()
    30  	ev := <-sub.Chan()
    31  
    32  	if ev.Data.(testEvent) != testEvent(5) {
    33  		t.Errorf("Got %v (%T), expected event %v (%T)",
    34  			ev, ev, testEvent(5), testEvent(5))
    35  	}
    36  }
    37  
    38  func TestMuxErrorAfterStop(t *testing.T) {
    39  	mux := new(TypeMux)
    40  	mux.Stop()
    41  
    42  	sub := mux.Subscribe(testEvent(0))
    43  	if _, isopen := <-sub.Chan(); isopen {
    44  		t.Errorf("subscription channel was not closed")
    45  	}
    46  	if err := mux.Post(testEvent(0)); err != ErrMuxClosed {
    47  		t.Errorf("Post error mismatch, got: %s, expected: %s", err, ErrMuxClosed)
    48  	}
    49  }
    50  
    51  func TestUnsubscribeUnblockPost(t *testing.T) {
    52  	mux := new(TypeMux)
    53  	defer mux.Stop()
    54  
    55  	sub := mux.Subscribe(testEvent(0))
    56  	unblocked := make(chan bool)
    57  	go func() {
    58  		mux.Post(testEvent(5))
    59  		unblocked <- true
    60  	}()
    61  
    62  	select {
    63  	case <-unblocked:
    64  		t.Errorf("Post returned before Unsubscribe")
    65  	default:
    66  		sub.Unsubscribe()
    67  		<-unblocked
    68  	}
    69  }
    70  
    71  func TestSubscribeDuplicateType(t *testing.T) {
    72  	mux := new(TypeMux)
    73  	expected := "event: duplicate type event.testEvent in Subscribe"
    74  
    75  	defer func() {
    76  		err := recover()
    77  		if err == nil {
    78  			t.Errorf("Subscribe didn't panic for duplicate type")
    79  		} else if err != expected {
    80  			t.Errorf("panic mismatch: got %#v, expected %#v", err, expected)
    81  		}
    82  	}()
    83  	mux.Subscribe(testEvent(1), testEvent(2))
    84  }
    85  
    86  func TestMuxConcurrent(t *testing.T) {
    87  	rand.Seed(time.Now().Unix())
    88  	mux := new(TypeMux)
    89  	defer mux.Stop()
    90  
    91  	recv := make(chan int)
    92  	poster := func() {
    93  		for {
    94  			err := mux.Post(testEvent(0))
    95  			if err != nil {
    96  				return
    97  			}
    98  		}
    99  	}
   100  	sub := func(i int) {
   101  		time.Sleep(time.Duration(rand.Intn(99)) * time.Millisecond)
   102  		sub := mux.Subscribe(testEvent(0))
   103  		<-sub.Chan()
   104  		sub.Unsubscribe()
   105  		recv <- i
   106  	}
   107  
   108  	go poster()
   109  	go poster()
   110  	go poster()
   111  	nsubs := 1000
   112  	for i := 0; i < nsubs; i++ {
   113  		go sub(i)
   114  	}
   115  
   116  	counts := make(map[int]int, nsubs)
   117  	for i := 0; i < nsubs; i++ {
   118  		counts[<-recv]++
   119  	}
   120  	for i, count := range counts {
   121  		if count != 1 {
   122  			t.Errorf("receiver %d called %d times, expected only 1 call", i, count)
   123  		}
   124  	}
   125  }
   126  
   127  func emptySubscriber(mux *TypeMux) {
   128  	s := mux.Subscribe(testEvent(0))
   129  	go func() {
   130  		for range s.Chan() {
   131  		}
   132  	}()
   133  }
   134  
   135  func BenchmarkPost1000(b *testing.B) {
   136  	var (
   137  		mux              = new(TypeMux)
   138  		subscribed, done sync.WaitGroup
   139  		nsubs            = 1000
   140  	)
   141  	subscribed.Add(nsubs)
   142  	done.Add(nsubs)
   143  	for i := 0; i < nsubs; i++ {
   144  		go func() {
   145  			s := mux.Subscribe(testEvent(0))
   146  			subscribed.Done()
   147  			for range s.Chan() {
   148  			}
   149  			done.Done()
   150  		}()
   151  	}
   152  	subscribed.Wait()
   153  
   154  	b.ResetTimer()
   155  	for i := 0; i < b.N; i++ {
   156  		mux.Post(testEvent(0))
   157  	}
   158  
   159  	b.StopTimer()
   160  	mux.Stop()
   161  	done.Wait()
   162  }
   163  
   164  func BenchmarkPostConcurrent(b *testing.B) {
   165  	var mux = new(TypeMux)
   166  	defer mux.Stop()
   167  	emptySubscriber(mux)
   168  	emptySubscriber(mux)
   169  	emptySubscriber(mux)
   170  
   171  	var wg sync.WaitGroup
   172  	poster := func() {
   173  		for i := 0; i < b.N; i++ {
   174  			mux.Post(testEvent(0))
   175  		}
   176  		wg.Done()
   177  	}
   178  	wg.Add(5)
   179  	for i := 0; i < 5; i++ {
   180  		go poster()
   181  	}
   182  	wg.Wait()
   183  }
   184  
   185  func BenchmarkChanSend(b *testing.B) {
   186  	c := make(chan interface{})
   187  	closed := make(chan struct{})
   188  	go func() {
   189  		for range c {
   190  		}
   191  	}()
   192  
   193  	for i := 0; i < b.N; i++ {
   194  		select {
   195  		case c <- i:
   196  		case <-closed:
   197  		}
   198  	}
   199  }