github.com/supragya/TendermintConnector@v0.0.0-20210619045051-113e32b84fb1/_deprecated_chains/cosmos/libs/pubsub/pubsub_test.go (about) 1 package pubsub_test 2 3 import ( 4 "context" 5 "fmt" 6 "runtime/debug" 7 "testing" 8 "time" 9 10 "github.com/stretchr/testify/assert" 11 "github.com/stretchr/testify/require" 12 13 "github.com/tendermint/tendermint/libs/log" 14 15 "github.com/tendermint/tendermint/libs/pubsub" 16 "github.com/tendermint/tendermint/libs/pubsub/query" 17 ) 18 19 const ( 20 clientID = "test-client" 21 ) 22 23 func TestSubscribe(t *testing.T) { 24 s := pubsub.NewServer() 25 s.SetLogger(log.TestingLogger()) 26 s.Start() 27 defer s.Stop() 28 29 ctx := context.Background() 30 ch := make(chan interface{}, 1) 31 err := s.Subscribe(ctx, clientID, query.Empty{}, ch) 32 require.NoError(t, err) 33 err = s.Publish(ctx, "Ka-Zar") 34 require.NoError(t, err) 35 assertReceive(t, "Ka-Zar", ch) 36 37 err = s.Publish(ctx, "Quicksilver") 38 require.NoError(t, err) 39 assertReceive(t, "Quicksilver", ch) 40 } 41 42 func TestDifferentClients(t *testing.T) { 43 s := pubsub.NewServer() 44 s.SetLogger(log.TestingLogger()) 45 s.Start() 46 defer s.Stop() 47 48 ctx := context.Background() 49 ch1 := make(chan interface{}, 1) 50 err := s.Subscribe(ctx, "client-1", query.MustParse("tm.events.type='NewBlock'"), ch1) 51 require.NoError(t, err) 52 err = s.PublishWithTags(ctx, "Iceman", pubsub.NewTagMap(map[string]string{"tm.events.type": "NewBlock"})) 53 require.NoError(t, err) 54 assertReceive(t, "Iceman", ch1) 55 56 ch2 := make(chan interface{}, 1) 57 err = s.Subscribe(ctx, "client-2", query.MustParse("tm.events.type='NewBlock' AND abci.account.name='Igor'"), ch2) 58 require.NoError(t, err) 59 err = s.PublishWithTags(ctx, "Ultimo", pubsub.NewTagMap(map[string]string{"tm.events.type": "NewBlock", "abci.account.name": "Igor"})) 60 require.NoError(t, err) 61 assertReceive(t, "Ultimo", ch1) 62 assertReceive(t, "Ultimo", ch2) 63 64 ch3 := make(chan interface{}, 1) 65 err = s.Subscribe(ctx, "client-3", query.MustParse("tm.events.type='NewRoundStep' AND abci.account.name='Igor' AND abci.invoice.number = 10"), ch3) 66 require.NoError(t, err) 67 err = s.PublishWithTags(ctx, "Valeria Richards", pubsub.NewTagMap(map[string]string{"tm.events.type": "NewRoundStep"})) 68 require.NoError(t, err) 69 assert.Zero(t, len(ch3)) 70 } 71 72 func TestClientSubscribesTwice(t *testing.T) { 73 s := pubsub.NewServer() 74 s.SetLogger(log.TestingLogger()) 75 s.Start() 76 defer s.Stop() 77 78 ctx := context.Background() 79 q := query.MustParse("tm.events.type='NewBlock'") 80 81 ch1 := make(chan interface{}, 1) 82 err := s.Subscribe(ctx, clientID, q, ch1) 83 require.NoError(t, err) 84 err = s.PublishWithTags(ctx, "Goblin Queen", pubsub.NewTagMap(map[string]string{"tm.events.type": "NewBlock"})) 85 require.NoError(t, err) 86 assertReceive(t, "Goblin Queen", ch1) 87 88 ch2 := make(chan interface{}, 1) 89 err = s.Subscribe(ctx, clientID, q, ch2) 90 require.Error(t, err) 91 92 err = s.PublishWithTags(ctx, "Spider-Man", pubsub.NewTagMap(map[string]string{"tm.events.type": "NewBlock"})) 93 require.NoError(t, err) 94 assertReceive(t, "Spider-Man", ch1) 95 } 96 97 func TestUnsubscribe(t *testing.T) { 98 s := pubsub.NewServer() 99 s.SetLogger(log.TestingLogger()) 100 s.Start() 101 defer s.Stop() 102 103 ctx := context.Background() 104 ch := make(chan interface{}) 105 err := s.Subscribe(ctx, clientID, query.MustParse("tm.events.type='NewBlock'"), ch) 106 require.NoError(t, err) 107 err = s.Unsubscribe(ctx, clientID, query.MustParse("tm.events.type='NewBlock'")) 108 require.NoError(t, err) 109 110 err = s.Publish(ctx, "Nick Fury") 111 require.NoError(t, err) 112 assert.Zero(t, len(ch), "Should not receive anything after Unsubscribe") 113 114 _, ok := <-ch 115 assert.False(t, ok) 116 } 117 118 func TestResubscribe(t *testing.T) { 119 s := pubsub.NewServer() 120 s.SetLogger(log.TestingLogger()) 121 s.Start() 122 defer s.Stop() 123 124 ctx := context.Background() 125 ch := make(chan interface{}) 126 err := s.Subscribe(ctx, clientID, query.Empty{}, ch) 127 require.NoError(t, err) 128 err = s.Unsubscribe(ctx, clientID, query.Empty{}) 129 require.NoError(t, err) 130 ch = make(chan interface{}) 131 err = s.Subscribe(ctx, clientID, query.Empty{}, ch) 132 require.NoError(t, err) 133 134 err = s.Publish(ctx, "Cable") 135 require.NoError(t, err) 136 assertReceive(t, "Cable", ch) 137 } 138 139 func TestUnsubscribeAll(t *testing.T) { 140 s := pubsub.NewServer() 141 s.SetLogger(log.TestingLogger()) 142 s.Start() 143 defer s.Stop() 144 145 ctx := context.Background() 146 ch1, ch2 := make(chan interface{}, 1), make(chan interface{}, 1) 147 err := s.Subscribe(ctx, clientID, query.MustParse("tm.events.type='NewBlock'"), ch1) 148 require.NoError(t, err) 149 err = s.Subscribe(ctx, clientID, query.MustParse("tm.events.type='NewBlockHeader'"), ch2) 150 require.NoError(t, err) 151 152 err = s.UnsubscribeAll(ctx, clientID) 153 require.NoError(t, err) 154 155 err = s.Publish(ctx, "Nick Fury") 156 require.NoError(t, err) 157 assert.Zero(t, len(ch1), "Should not receive anything after UnsubscribeAll") 158 assert.Zero(t, len(ch2), "Should not receive anything after UnsubscribeAll") 159 160 _, ok := <-ch1 161 assert.False(t, ok) 162 _, ok = <-ch2 163 assert.False(t, ok) 164 } 165 166 func TestBufferCapacity(t *testing.T) { 167 s := pubsub.NewServer(pubsub.BufferCapacity(2)) 168 s.SetLogger(log.TestingLogger()) 169 170 assert.Equal(t, 2, s.BufferCapacity()) 171 172 ctx := context.Background() 173 err := s.Publish(ctx, "Nighthawk") 174 require.NoError(t, err) 175 err = s.Publish(ctx, "Sage") 176 require.NoError(t, err) 177 178 ctx, cancel := context.WithTimeout(ctx, 10*time.Millisecond) 179 defer cancel() 180 err = s.Publish(ctx, "Ironclad") 181 if assert.Error(t, err) { 182 assert.Equal(t, context.DeadlineExceeded, err) 183 } 184 } 185 186 func Benchmark10Clients(b *testing.B) { benchmarkNClients(10, b) } 187 func Benchmark100Clients(b *testing.B) { benchmarkNClients(100, b) } 188 func Benchmark1000Clients(b *testing.B) { benchmarkNClients(1000, b) } 189 190 func Benchmark10ClientsOneQuery(b *testing.B) { benchmarkNClientsOneQuery(10, b) } 191 func Benchmark100ClientsOneQuery(b *testing.B) { benchmarkNClientsOneQuery(100, b) } 192 func Benchmark1000ClientsOneQuery(b *testing.B) { benchmarkNClientsOneQuery(1000, b) } 193 194 func benchmarkNClients(n int, b *testing.B) { 195 s := pubsub.NewServer() 196 s.Start() 197 defer s.Stop() 198 199 ctx := context.Background() 200 for i := 0; i < n; i++ { 201 ch := make(chan interface{}) 202 go func() { 203 for range ch { 204 } 205 }() 206 s.Subscribe(ctx, clientID, query.MustParse(fmt.Sprintf("abci.Account.Owner = 'Ivan' AND abci.Invoices.Number = %d", i)), ch) 207 } 208 209 b.ReportAllocs() 210 b.ResetTimer() 211 for i := 0; i < b.N; i++ { 212 s.PublishWithTags(ctx, "Gamora", pubsub.NewTagMap(map[string]string{"abci.Account.Owner": "Ivan", "abci.Invoices.Number": string(i)})) 213 } 214 } 215 216 func benchmarkNClientsOneQuery(n int, b *testing.B) { 217 s := pubsub.NewServer() 218 s.Start() 219 defer s.Stop() 220 221 ctx := context.Background() 222 q := query.MustParse("abci.Account.Owner = 'Ivan' AND abci.Invoices.Number = 1") 223 for i := 0; i < n; i++ { 224 ch := make(chan interface{}) 225 go func() { 226 for range ch { 227 } 228 }() 229 s.Subscribe(ctx, clientID, q, ch) 230 } 231 232 b.ReportAllocs() 233 b.ResetTimer() 234 for i := 0; i < b.N; i++ { 235 s.PublishWithTags(ctx, "Gamora", pubsub.NewTagMap(map[string]string{"abci.Account.Owner": "Ivan", "abci.Invoices.Number": "1"})) 236 } 237 } 238 239 /////////////////////////////////////////////////////////////////////////////// 240 /// HELPERS 241 /////////////////////////////////////////////////////////////////////////////// 242 243 func assertReceive(t *testing.T, expected interface{}, ch <-chan interface{}, msgAndArgs ...interface{}) { 244 select { 245 case actual := <-ch: 246 if actual != nil { 247 assert.Equal(t, expected, actual, msgAndArgs...) 248 } 249 case <-time.After(1 * time.Second): 250 t.Errorf("Expected to receive %v from the channel, got nothing after 1s", expected) 251 debug.PrintStack() 252 } 253 }