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