github.com/linapex/ethereum-go-chinese@v0.0.0-20190316121929-f8b7a73c3fa1/event/feed_test.go (about)

     1  
     2  //<developer>
     3  //    <name>linapex 曹一峰</name>
     4  //    <email>linapex@163.com</email>
     5  //    <wx>superexc</wx>
     6  //    <qqgroup>128148617</qqgroup>
     7  //    <url>https://jsq.ink</url>
     8  //    <role>pku engineer</role>
     9  //    <date>2019-03-16 19:16:38</date>
    10  //</624450091108798464>
    11  
    12  
    13  package event
    14  
    15  import (
    16  	"fmt"
    17  	"reflect"
    18  	"sync"
    19  	"testing"
    20  	"time"
    21  )
    22  
    23  func TestFeedPanics(t *testing.T) {
    24  	{
    25  		var f Feed
    26  		f.Send(int(2))
    27  		want := feedTypeError{op: "Send", got: reflect.TypeOf(uint64(0)), want: reflect.TypeOf(int(0))}
    28  		if err := checkPanic(want, func() { f.Send(uint64(2)) }); err != nil {
    29  			t.Error(err)
    30  		}
    31  	}
    32  	{
    33  		var f Feed
    34  		ch := make(chan int)
    35  		f.Subscribe(ch)
    36  		want := feedTypeError{op: "Send", got: reflect.TypeOf(uint64(0)), want: reflect.TypeOf(int(0))}
    37  		if err := checkPanic(want, func() { f.Send(uint64(2)) }); err != nil {
    38  			t.Error(err)
    39  		}
    40  	}
    41  	{
    42  		var f Feed
    43  		f.Send(int(2))
    44  		want := feedTypeError{op: "Subscribe", got: reflect.TypeOf(make(chan uint64)), want: reflect.TypeOf(make(chan<- int))}
    45  		if err := checkPanic(want, func() { f.Subscribe(make(chan uint64)) }); err != nil {
    46  			t.Error(err)
    47  		}
    48  	}
    49  	{
    50  		var f Feed
    51  		if err := checkPanic(errBadChannel, func() { f.Subscribe(make(<-chan int)) }); err != nil {
    52  			t.Error(err)
    53  		}
    54  	}
    55  	{
    56  		var f Feed
    57  		if err := checkPanic(errBadChannel, func() { f.Subscribe(int(0)) }); err != nil {
    58  			t.Error(err)
    59  		}
    60  	}
    61  }
    62  
    63  func checkPanic(want error, fn func()) (err error) {
    64  	defer func() {
    65  		panic := recover()
    66  		if panic == nil {
    67  			err = fmt.Errorf("didn't panic")
    68  		} else if !reflect.DeepEqual(panic, want) {
    69  			err = fmt.Errorf("panicked with wrong error: got %q, want %q", panic, want)
    70  		}
    71  	}()
    72  	fn()
    73  	return nil
    74  }
    75  
    76  func TestFeed(t *testing.T) {
    77  	var feed Feed
    78  	var done, subscribed sync.WaitGroup
    79  	subscriber := func(i int) {
    80  		defer done.Done()
    81  
    82  		subchan := make(chan int)
    83  		sub := feed.Subscribe(subchan)
    84  		timeout := time.NewTimer(2 * time.Second)
    85  		subscribed.Done()
    86  
    87  		select {
    88  		case v := <-subchan:
    89  			if v != 1 {
    90  				t.Errorf("%d: received value %d, want 1", i, v)
    91  			}
    92  		case <-timeout.C:
    93  			t.Errorf("%d: receive timeout", i)
    94  		}
    95  
    96  		sub.Unsubscribe()
    97  		select {
    98  		case _, ok := <-sub.Err():
    99  			if ok {
   100  				t.Errorf("%d: error channel not closed after unsubscribe", i)
   101  			}
   102  		case <-timeout.C:
   103  			t.Errorf("%d: unsubscribe timeout", i)
   104  		}
   105  	}
   106  
   107  	const n = 1000
   108  	done.Add(n)
   109  	subscribed.Add(n)
   110  	for i := 0; i < n; i++ {
   111  		go subscriber(i)
   112  	}
   113  	subscribed.Wait()
   114  	if nsent := feed.Send(1); nsent != n {
   115  		t.Errorf("first send delivered %d times, want %d", nsent, n)
   116  	}
   117  	if nsent := feed.Send(2); nsent != 0 {
   118  		t.Errorf("second send delivered %d times, want 0", nsent)
   119  	}
   120  	done.Wait()
   121  }
   122  
   123  func TestFeedSubscribeSameChannel(t *testing.T) {
   124  	var (
   125  		feed Feed
   126  		done sync.WaitGroup
   127  		ch   = make(chan int)
   128  		sub1 = feed.Subscribe(ch)
   129  		sub2 = feed.Subscribe(ch)
   130  		_    = feed.Subscribe(ch)
   131  	)
   132  	expectSends := func(value, n int) {
   133  		if nsent := feed.Send(value); nsent != n {
   134  			t.Errorf("send delivered %d times, want %d", nsent, n)
   135  		}
   136  		done.Done()
   137  	}
   138  	expectRecv := func(wantValue, n int) {
   139  		for i := 0; i < n; i++ {
   140  			if v := <-ch; v != wantValue {
   141  				t.Errorf("received %d, want %d", v, wantValue)
   142  			}
   143  		}
   144  	}
   145  
   146  	done.Add(1)
   147  	go expectSends(1, 3)
   148  	expectRecv(1, 3)
   149  	done.Wait()
   150  
   151  	sub1.Unsubscribe()
   152  
   153  	done.Add(1)
   154  	go expectSends(2, 2)
   155  	expectRecv(2, 2)
   156  	done.Wait()
   157  
   158  	sub2.Unsubscribe()
   159  
   160  	done.Add(1)
   161  	go expectSends(3, 1)
   162  	expectRecv(3, 1)
   163  	done.Wait()
   164  }
   165  
   166  func TestFeedSubscribeBlockedPost(t *testing.T) {
   167  	var (
   168  		feed   Feed
   169  		nsends = 2000
   170  		ch1    = make(chan int)
   171  		ch2    = make(chan int)
   172  		wg     sync.WaitGroup
   173  	)
   174  	defer wg.Wait()
   175  
   176  	feed.Subscribe(ch1)
   177  	wg.Add(nsends)
   178  	for i := 0; i < nsends; i++ {
   179  		go func() {
   180  			feed.Send(99)
   181  			wg.Done()
   182  		}()
   183  	}
   184  
   185  	sub2 := feed.Subscribe(ch2)
   186  	defer sub2.Unsubscribe()
   187  
   188  //当ch1收到n次时,我们就完成了。
   189  //CH2上的接收数取决于调度。
   190  	for i := 0; i < nsends; {
   191  		select {
   192  		case <-ch1:
   193  			i++
   194  		case <-ch2:
   195  		}
   196  	}
   197  }
   198  
   199  func TestFeedUnsubscribeBlockedPost(t *testing.T) {
   200  	var (
   201  		feed   Feed
   202  		nsends = 200
   203  		chans  = make([]chan int, 2000)
   204  		subs   = make([]Subscription, len(chans))
   205  		bchan  = make(chan int)
   206  		bsub   = feed.Subscribe(bchan)
   207  		wg     sync.WaitGroup
   208  	)
   209  	for i := range chans {
   210  		chans[i] = make(chan int, nsends)
   211  	}
   212  
   213  //排队发送一些邮件。当bchan不被读取时,这些都不能取得进展。
   214  	wg.Add(nsends)
   215  	for i := 0; i < nsends; i++ {
   216  		go func() {
   217  			feed.Send(99)
   218  			wg.Done()
   219  		}()
   220  	}
   221  //订阅其他频道。
   222  	for i, ch := range chans {
   223  		subs[i] = feed.Subscribe(ch)
   224  	}
   225  //再次取消订阅。
   226  	for _, sub := range subs {
   227  		sub.Unsubscribe()
   228  	}
   229  //取消阻止发送。
   230  	bsub.Unsubscribe()
   231  	wg.Wait()
   232  }
   233  
   234  //检查在发送期间取消订阅频道是否有效
   235  //频道已发送。
   236  func TestFeedUnsubscribeSentChan(t *testing.T) {
   237  	var (
   238  		feed Feed
   239  		ch1  = make(chan int)
   240  		ch2  = make(chan int)
   241  		sub1 = feed.Subscribe(ch1)
   242  		sub2 = feed.Subscribe(ch2)
   243  		wg   sync.WaitGroup
   244  	)
   245  	defer sub2.Unsubscribe()
   246  
   247  	wg.Add(1)
   248  	go func() {
   249  		feed.Send(0)
   250  		wg.Done()
   251  	}()
   252  
   253  //等待ch1上的值。
   254  	<-ch1
   255  //取消订阅ch1,将其从发送案例中删除。
   256  	sub1.Unsubscribe()
   257  
   258  //接收CH2,完成发送。
   259  	<-ch2
   260  	wg.Wait()
   261  
   262  //再发一次。这应该只发送到ch2,因此等待组将取消阻止
   263  //一旦收到CH2上的值。
   264  	wg.Add(1)
   265  	go func() {
   266  		feed.Send(0)
   267  		wg.Done()
   268  	}()
   269  	<-ch2
   270  	wg.Wait()
   271  }
   272  
   273  func TestFeedUnsubscribeFromInbox(t *testing.T) {
   274  	var (
   275  		feed Feed
   276  		ch1  = make(chan int)
   277  		ch2  = make(chan int)
   278  		sub1 = feed.Subscribe(ch1)
   279  		sub2 = feed.Subscribe(ch1)
   280  		sub3 = feed.Subscribe(ch2)
   281  	)
   282  	if len(feed.inbox) != 3 {
   283  		t.Errorf("inbox length != 3 after subscribe")
   284  	}
   285  	if len(feed.sendCases) != 1 {
   286  		t.Errorf("sendCases is non-empty after unsubscribe")
   287  	}
   288  
   289  	sub1.Unsubscribe()
   290  	sub2.Unsubscribe()
   291  	sub3.Unsubscribe()
   292  	if len(feed.inbox) != 0 {
   293  		t.Errorf("inbox is non-empty after unsubscribe")
   294  	}
   295  	if len(feed.sendCases) != 1 {
   296  		t.Errorf("sendCases is non-empty after unsubscribe")
   297  	}
   298  }
   299  
   300  func BenchmarkFeedSend1000(b *testing.B) {
   301  	var (
   302  		done  sync.WaitGroup
   303  		feed  Feed
   304  		nsubs = 1000
   305  	)
   306  	subscriber := func(ch <-chan int) {
   307  		for i := 0; i < b.N; i++ {
   308  			<-ch
   309  		}
   310  		done.Done()
   311  	}
   312  	done.Add(nsubs)
   313  	for i := 0; i < nsubs; i++ {
   314  		ch := make(chan int, 200)
   315  		feed.Subscribe(ch)
   316  		go subscriber(ch)
   317  	}
   318  
   319  //实际基准。
   320  	b.ResetTimer()
   321  	for i := 0; i < b.N; i++ {
   322  		if feed.Send(i) != nsubs {
   323  			panic("wrong number of sends")
   324  		}
   325  	}
   326  
   327  	b.StopTimer()
   328  	done.Wait()
   329  }
   330