github.com/tenywen/fabric@v1.0.0-beta.0.20170620030522-a5b1ed380643/gossip/util/pubsub_test.go (about) 1 /* 2 Copyright IBM Corp. 2017 All Rights Reserved. 3 4 Licensed under the Apache License, Version 2.0 (the "License"); 5 you may not use this file except in compliance with the License. 6 You may obtain a copy of the License at 7 8 http://www.apache.org/licenses/LICENSE-2.0 9 10 Unless required by applicable law or agreed to in writing, software 11 distributed under the License is distributed on an "AS IS" BASIS, 12 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 See the License for the specific language governing permissions and 14 limitations under the License. 15 */ 16 17 package util 18 19 import ( 20 "sync" 21 "testing" 22 "time" 23 24 "github.com/stretchr/testify/assert" 25 ) 26 27 func TestNewPubsub(t *testing.T) { 28 ps := NewPubSub() 29 // Check a publishing to a topic with a subscription succeeds 30 sub1 := ps.Subscribe("test", time.Second) 31 sub2 := ps.Subscribe("test2", time.Second) 32 assert.NotNil(t, sub1) 33 go func() { 34 err := ps.Publish("test", 5) 35 assert.NoError(t, err) 36 }() 37 item, err := sub1.Listen() 38 assert.NoError(t, err) 39 assert.Equal(t, 5, item) 40 // Check that a publishing to a topic with no subscribers fails 41 err = ps.Publish("test3", 5) 42 assert.Error(t, err) 43 assert.Contains(t, "no subscribers", err.Error()) 44 // Check that a listen on a topic that its publish is too late, times out 45 // and returns an error 46 go func() { 47 time.Sleep(time.Second * 2) 48 ps.Publish("test2", 10) 49 }() 50 item, err = sub2.Listen() 51 assert.Error(t, err) 52 assert.Contains(t, "timed out", err.Error()) 53 assert.Nil(t, item) 54 // Have multiple subscribers subscribe to the same topic 55 subscriptions := []Subscription{} 56 n := 100 57 for i := 0; i < n; i++ { 58 subscriptions = append(subscriptions, ps.Subscribe("test4", time.Second)) 59 } 60 go func() { 61 // Send items and fill the buffer and overflow 62 // it by 1 item 63 for i := 0; i <= subscriptionBuffSize; i++ { 64 err := ps.Publish("test4", 100+i) 65 assert.NoError(t, err) 66 } 67 }() 68 wg := sync.WaitGroup{} 69 wg.Add(n) 70 for _, s := range subscriptions { 71 go func(s Subscription) { 72 time.Sleep(time.Second) 73 defer wg.Done() 74 for i := 0; i < subscriptionBuffSize; i++ { 75 item, err := s.Listen() 76 assert.NoError(t, err) 77 assert.Equal(t, 100+i, item) 78 } 79 // The last item that we published was dropped 80 // due to the buffer being full 81 item, err := s.Listen() 82 assert.Nil(t, item) 83 assert.Error(t, err) 84 }(s) 85 } 86 wg.Wait() 87 88 // Ensure subscriptions are cleaned after use 89 for i := 0; i < 10; i++ { 90 time.Sleep(time.Second) 91 ps.Lock() 92 empty := len(ps.subscriptions) == 0 93 ps.Unlock() 94 if empty { 95 break 96 } 97 } 98 ps.Lock() 99 defer ps.Unlock() 100 assert.Empty(t, ps.subscriptions) 101 }