github.com/sberex/go-sberex@v1.8.2-0.20181113200658-ed96ac38f7d7/event/event_test.go (about)

     1  // This file is part of the go-sberex library. The go-sberex library is 
     2  // free software: you can redistribute it and/or modify it under the terms 
     3  // of the GNU Lesser General Public License as published by the Free 
     4  // Software Foundation, either version 3 of the License, or (at your option)
     5  // any later version.
     6  //
     7  // The go-sberex library is distributed in the hope that it will be useful, 
     8  // but WITHOUT ANY WARRANTY; without even the implied warranty of
     9  // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser 
    10  // General Public License <http://www.gnu.org/licenses/> for more details.
    11  
    12  package event
    13  
    14  import (
    15  	"math/rand"
    16  	"sync"
    17  	"testing"
    18  	"time"
    19  )
    20  
    21  type testEvent int
    22  
    23  func TestSubCloseUnsub(t *testing.T) {
    24  	// the point of this test is **not** to panic
    25  	var mux TypeMux
    26  	mux.Stop()
    27  	sub := mux.Subscribe(int(0))
    28  	sub.Unsubscribe()
    29  }
    30  
    31  func TestSub(t *testing.T) {
    32  	mux := new(TypeMux)
    33  	defer mux.Stop()
    34  
    35  	sub := mux.Subscribe(testEvent(0))
    36  	go func() {
    37  		if err := mux.Post(testEvent(5)); err != nil {
    38  			t.Errorf("Post returned unexpected error: %v", err)
    39  		}
    40  	}()
    41  	ev := <-sub.Chan()
    42  
    43  	if ev.Data.(testEvent) != testEvent(5) {
    44  		t.Errorf("Got %v (%T), expected event %v (%T)",
    45  			ev, ev, testEvent(5), testEvent(5))
    46  	}
    47  }
    48  
    49  func TestMuxErrorAfterStop(t *testing.T) {
    50  	mux := new(TypeMux)
    51  	mux.Stop()
    52  
    53  	sub := mux.Subscribe(testEvent(0))
    54  	if _, isopen := <-sub.Chan(); isopen {
    55  		t.Errorf("subscription channel was not closed")
    56  	}
    57  	if err := mux.Post(testEvent(0)); err != ErrMuxClosed {
    58  		t.Errorf("Post error mismatch, got: %s, expected: %s", err, ErrMuxClosed)
    59  	}
    60  }
    61  
    62  func TestUnsubscribeUnblockPost(t *testing.T) {
    63  	mux := new(TypeMux)
    64  	defer mux.Stop()
    65  
    66  	sub := mux.Subscribe(testEvent(0))
    67  	unblocked := make(chan bool)
    68  	go func() {
    69  		mux.Post(testEvent(5))
    70  		unblocked <- true
    71  	}()
    72  
    73  	select {
    74  	case <-unblocked:
    75  		t.Errorf("Post returned before Unsubscribe")
    76  	default:
    77  		sub.Unsubscribe()
    78  		<-unblocked
    79  	}
    80  }
    81  
    82  func TestSubscribeDuplicateType(t *testing.T) {
    83  	mux := new(TypeMux)
    84  	expected := "event: duplicate type event.testEvent in Subscribe"
    85  
    86  	defer func() {
    87  		err := recover()
    88  		if err == nil {
    89  			t.Errorf("Subscribe didn't panic for duplicate type")
    90  		} else if err != expected {
    91  			t.Errorf("panic mismatch: got %#v, expected %#v", err, expected)
    92  		}
    93  	}()
    94  	mux.Subscribe(testEvent(1), testEvent(2))
    95  }
    96  
    97  func TestMuxConcurrent(t *testing.T) {
    98  	rand.Seed(time.Now().Unix())
    99  	mux := new(TypeMux)
   100  	defer mux.Stop()
   101  
   102  	recv := make(chan int)
   103  	poster := func() {
   104  		for {
   105  			err := mux.Post(testEvent(0))
   106  			if err != nil {
   107  				return
   108  			}
   109  		}
   110  	}
   111  	sub := func(i int) {
   112  		time.Sleep(time.Duration(rand.Intn(99)) * time.Millisecond)
   113  		sub := mux.Subscribe(testEvent(0))
   114  		<-sub.Chan()
   115  		sub.Unsubscribe()
   116  		recv <- i
   117  	}
   118  
   119  	go poster()
   120  	go poster()
   121  	go poster()
   122  	nsubs := 1000
   123  	for i := 0; i < nsubs; i++ {
   124  		go sub(i)
   125  	}
   126  
   127  	// wait until everyone has been served
   128  	counts := make(map[int]int, nsubs)
   129  	for i := 0; i < nsubs; i++ {
   130  		counts[<-recv]++
   131  	}
   132  	for i, count := range counts {
   133  		if count != 1 {
   134  			t.Errorf("receiver %d called %d times, expected only 1 call", i, count)
   135  		}
   136  	}
   137  }
   138  
   139  func emptySubscriber(mux *TypeMux, types ...interface{}) {
   140  	s := mux.Subscribe(testEvent(0))
   141  	go func() {
   142  		for range s.Chan() {
   143  		}
   144  	}()
   145  }
   146  
   147  func BenchmarkPost1000(b *testing.B) {
   148  	var (
   149  		mux              = new(TypeMux)
   150  		subscribed, done sync.WaitGroup
   151  		nsubs            = 1000
   152  	)
   153  	subscribed.Add(nsubs)
   154  	done.Add(nsubs)
   155  	for i := 0; i < nsubs; i++ {
   156  		go func() {
   157  			s := mux.Subscribe(testEvent(0))
   158  			subscribed.Done()
   159  			for range s.Chan() {
   160  			}
   161  			done.Done()
   162  		}()
   163  	}
   164  	subscribed.Wait()
   165  
   166  	// The actual benchmark.
   167  	b.ResetTimer()
   168  	for i := 0; i < b.N; i++ {
   169  		mux.Post(testEvent(0))
   170  	}
   171  
   172  	b.StopTimer()
   173  	mux.Stop()
   174  	done.Wait()
   175  }
   176  
   177  func BenchmarkPostConcurrent(b *testing.B) {
   178  	var mux = new(TypeMux)
   179  	defer mux.Stop()
   180  	emptySubscriber(mux, testEvent(0))
   181  	emptySubscriber(mux, testEvent(0))
   182  	emptySubscriber(mux, testEvent(0))
   183  
   184  	var wg sync.WaitGroup
   185  	poster := func() {
   186  		for i := 0; i < b.N; i++ {
   187  			mux.Post(testEvent(0))
   188  		}
   189  		wg.Done()
   190  	}
   191  	wg.Add(5)
   192  	for i := 0; i < 5; i++ {
   193  		go poster()
   194  	}
   195  	wg.Wait()
   196  }
   197  
   198  // for comparison
   199  func BenchmarkChanSend(b *testing.B) {
   200  	c := make(chan interface{})
   201  	closed := make(chan struct{})
   202  	go func() {
   203  		for range c {
   204  		}
   205  	}()
   206  
   207  	for i := 0; i < b.N; i++ {
   208  		select {
   209  		case c <- i:
   210  		case <-closed:
   211  		}
   212  	}
   213  }