github.com/sykesm/fabric@v1.1.0-preview.0.20200129034918-2aa12b1a0181/gossip/util/pubsub_test.go (about)

     1  /*
     2  Copyright IBM Corp. All Rights Reserved.
     3  
     4  SPDX-License-Identifier: Apache-2.0
     5  */
     6  
     7  package util
     8  
     9  import (
    10  	"sync"
    11  	"testing"
    12  	"time"
    13  
    14  	"github.com/stretchr/testify/assert"
    15  )
    16  
    17  func TestNewPubsub(t *testing.T) {
    18  	ps := NewPubSub()
    19  	// Check a publishing to a topic with a subscription succeeds
    20  	sub1 := ps.Subscribe("test", time.Second)
    21  	sub2 := ps.Subscribe("test2", time.Second)
    22  	assert.NotNil(t, sub1)
    23  	go func() {
    24  		err := ps.Publish("test", 5)
    25  		assert.NoError(t, err)
    26  	}()
    27  	item, err := sub1.Listen()
    28  	assert.NoError(t, err)
    29  	assert.Equal(t, 5, item)
    30  	// Check that a publishing to a topic with no subscribers fails
    31  	err = ps.Publish("test3", 5)
    32  	assert.Error(t, err)
    33  	assert.Contains(t, "no subscribers", err.Error())
    34  	// Check that a listen on a topic that its publish is too late, times out
    35  	// and returns an error
    36  	go func() {
    37  		time.Sleep(time.Second * 2)
    38  		ps.Publish("test2", 10)
    39  	}()
    40  	item, err = sub2.Listen()
    41  	assert.Error(t, err)
    42  	assert.Contains(t, "timed out", err.Error())
    43  	assert.Nil(t, item)
    44  	// Have multiple subscribers subscribe to the same topic
    45  	subscriptions := []Subscription{}
    46  	n := 100
    47  	for i := 0; i < n; i++ {
    48  		subscriptions = append(subscriptions, ps.Subscribe("test4", time.Second))
    49  	}
    50  	go func() {
    51  		// Send items and fill the buffer and overflow
    52  		// it by 1 item
    53  		for i := 0; i <= subscriptionBuffSize; i++ {
    54  			err := ps.Publish("test4", 100+i)
    55  			assert.NoError(t, err)
    56  		}
    57  	}()
    58  	wg := sync.WaitGroup{}
    59  	wg.Add(n)
    60  	for _, s := range subscriptions {
    61  		go func(s Subscription) {
    62  			time.Sleep(time.Second)
    63  			defer wg.Done()
    64  			for i := 0; i < subscriptionBuffSize; i++ {
    65  				item, err := s.Listen()
    66  				assert.NoError(t, err)
    67  				assert.Equal(t, 100+i, item)
    68  			}
    69  			// The last item that we published was dropped
    70  			// due to the buffer being full
    71  			item, err := s.Listen()
    72  			assert.Nil(t, item)
    73  			assert.Error(t, err)
    74  		}(s)
    75  	}
    76  	wg.Wait()
    77  
    78  	// Ensure subscriptions are cleaned after use
    79  	for i := 0; i < 10; i++ {
    80  		time.Sleep(time.Second)
    81  		ps.Lock()
    82  		empty := len(ps.subscriptions) == 0
    83  		ps.Unlock()
    84  		if empty {
    85  			break
    86  		}
    87  	}
    88  	ps.Lock()
    89  	defer ps.Unlock()
    90  	assert.Empty(t, ps.subscriptions)
    91  }