@ -27,16 +27,15 @@ func TestSubscribe(t *testing.T) {
defer s . Stop ( )
ctx := context . Background ( )
ch := make ( chan interface { } , 1 )
err := s . Subscribe ( ctx , clientID , query . Empty { } , ch )
subscription , err := s . Subscribe ( ctx , clientID , query . Empty { } , 1 )
require . NoError ( t , err )
err = s . Publish ( ctx , "Ka-Zar" )
require . NoError ( t , err )
assertReceive ( t , "Ka-Zar" , ch )
assertReceive ( t , "Ka-Zar" , subscription . Out ( ) )
err = s . Publish ( ctx , "Quicksilver" )
require . NoError ( t , err )
assertReceive ( t , "Quicksilver" , ch )
assertReceive ( t , "Quicksilver" , subscription . Out ( ) )
}
func TestDifferentClients ( t * testing . T ) {
@ -46,27 +45,24 @@ func TestDifferentClients(t *testing.T) {
defer s . Stop ( )
ctx := context . Background ( )
ch1 := make ( chan interface { } , 1 )
err := s . Subscribe ( ctx , "client-1" , query . MustParse ( "tm.events.type='NewBlock'" ) , ch1 )
subscription1 , err := s . Subscribe ( ctx , "client-1" , query . MustParse ( "tm.events.type='NewBlock'" ) , 1 )
require . NoError ( t , err )
err = s . PublishWithTags ( ctx , "Iceman" , pubsub . NewTagMap ( map [ string ] string { "tm.events.type" : "NewBlock" } ) )
require . NoError ( t , err )
assertReceive ( t , "Iceman" , ch1 )
assertReceive ( t , "Iceman" , subscription1 . Out ( ) )
ch2 := make ( chan interface { } , 1 )
err = s . Subscribe ( ctx , "client-2" , query . MustParse ( "tm.events.type='NewBlock' AND abci.account.name='Igor'" ) , ch2 )
subscription2 , err := s . Subscribe ( ctx , "client-2" , query . MustParse ( "tm.events.type='NewBlock' AND abci.account.name='Igor'" ) , 1 )
require . NoError ( t , err )
err = s . PublishWithTags ( ctx , "Ultimo" , pubsub . NewTagMap ( map [ string ] string { "tm.events.type" : "NewBlock" , "abci.account.name" : "Igor" } ) )
require . NoError ( t , err )
assertReceive ( t , "Ultimo" , ch1 )
assertReceive ( t , "Ultimo" , ch2 )
assertReceive ( t , "Ultimo" , subscription1 . Out ( ) )
assertReceive ( t , "Ultimo" , subscription2 . Out ( ) )
ch3 := make ( chan interface { } , 1 )
err = s . Subscribe ( ctx , "client-3" , query . MustParse ( "tm.events.type='NewRoundStep' AND abci.account.name='Igor' AND abci.invoice.number = 10" ) , ch3 )
subscription3 , err := s . Subscribe ( ctx , "client-3" , query . MustParse ( "tm.events.type='NewRoundStep' AND abci.account.name='Igor' AND abci.invoice.number = 10" ) , 1 )
require . NoError ( t , err )
err = s . PublishWithTags ( ctx , "Valeria Richards" , pubsub . NewTagMap ( map [ string ] string { "tm.events.type" : "NewRoundStep" } ) )
require . NoError ( t , err )
assert . Zero ( t , len ( ch3 ) )
assert . Zero ( t , len ( subscription3 . Out ( ) ) )
}
func TestClientSubscribesTwice ( t * testing . T ) {
@ -78,20 +74,19 @@ func TestClientSubscribesTwice(t *testing.T) {
ctx := context . Background ( )
q := query . MustParse ( "tm.events.type='NewBlock'" )
ch1 := make ( chan interface { } , 1 )
err := s . Subscribe ( ctx , clientID , q , ch1 )
subscription1 , err := s . Subscribe ( ctx , clientID , q , 1 )
require . NoError ( t , err )
err = s . PublishWithTags ( ctx , "Goblin Queen" , pubsub . NewTagMap ( map [ string ] string { "tm.events.type" : "NewBlock" } ) )
require . NoError ( t , err )
assertReceive ( t , "Goblin Queen" , ch1 )
assertReceive ( t , "Goblin Queen" , subscription1 . Out ( ) )
ch2 := make ( chan interface { } , 1 )
err = s . Subscribe ( ctx , clientID , q , ch2 )
subscription2 , err := s . Subscribe ( ctx , clientID , q , 1 )
require . Error ( t , err )
require . Nil ( t , subscription2 )
err = s . PublishWithTags ( ctx , "Spider-Man" , pubsub . NewTagMap ( map [ string ] string { "tm.events.type" : "NewBlock" } ) )
require . NoError ( t , err )
assertReceive ( t , "Spider-Man" , ch1 )
assertReceive ( t , "Spider-Man" , subscription1 . Out ( ) )
}
func TestUnsubscribe ( t * testing . T ) {
@ -101,18 +96,19 @@ func TestUnsubscribe(t *testing.T) {
defer s . Stop ( )
ctx := context . Background ( )
ch := make ( chan interface { } )
err := s . Subscribe ( ctx , clientID , query . MustParse ( "tm.events.type='NewBlock'" ) , ch )
subscription , err := s . Subscribe ( ctx , clientID , query . MustParse ( "tm.events.type='NewBlock'" ) , 1 )
require . NoError ( t , err )
err = s . Unsubscribe ( ctx , clientID , query . MustParse ( "tm.events.type='NewBlock'" ) )
require . NoError ( t , err )
err = s . Publish ( ctx , "Nick Fury" )
require . NoError ( t , err )
assert . Zero ( t , len ( ch ) , "Should not receive anything after Unsubscribe" )
assert . Zero ( t , len ( subscription . Out ( ) ) , "Should not receive anything after Unsubscribe" )
_ , ok := <- ch
_ , ok := <- subscription . Cancelled ( )
assert . False ( t , ok )
assert . Equal ( t , pubsub . ErrUnsubscribed , subscription . Err ( ) )
}
func TestClientUnsubscribesTwice ( t * testing . T ) {
@ -122,8 +118,7 @@ func TestClientUnsubscribesTwice(t *testing.T) {
defer s . Stop ( )
ctx := context . Background ( )
ch := make ( chan interface { } )
err := s . Subscribe ( ctx , clientID , query . MustParse ( "tm.events.type='NewBlock'" ) , ch )
_ , err := s . Subscribe ( ctx , clientID , query . MustParse ( "tm.events.type='NewBlock'" ) , 1 )
require . NoError ( t , err )
err = s . Unsubscribe ( ctx , clientID , query . MustParse ( "tm.events.type='NewBlock'" ) )
require . NoError ( t , err )
@ -141,18 +136,16 @@ func TestResubscribe(t *testing.T) {
defer s . Stop ( )
ctx := context . Background ( )
ch := make ( chan interface { } )
err := s . Subscribe ( ctx , clientID , query . Empty { } , ch )
subscription , err := s . Subscribe ( ctx , clientID , query . Empty { } , 1 )
require . NoError ( t , err )
err = s . Unsubscribe ( ctx , clientID , query . Empty { } )
require . NoError ( t , err )
ch = make ( chan interface { } )
err = s . Subscribe ( ctx , clientID , query . Empty { } , ch )
subscription , err = s . Subscribe ( ctx , clientID , query . Empty { } , 1 )
require . NoError ( t , err )
err = s . Publish ( ctx , "Cable" )
require . NoError ( t , err )
assertReceive ( t , "Cable" , ch )
assertReceive ( t , "Cable" , subscription . Out ( ) )
}
func TestUnsubscribeAll ( t * testing . T ) {
@ -162,10 +155,9 @@ func TestUnsubscribeAll(t *testing.T) {
defer s . Stop ( )
ctx := context . Background ( )
ch1 , ch2 := make ( chan interface { } , 1 ) , make ( chan interface { } , 1 )
err := s . Subscribe ( ctx , clientID , query . MustParse ( "tm.events.type='NewBlock'" ) , ch1 )
subscription1 , err := s . Subscribe ( ctx , clientID , query . MustParse ( "tm.events.type='NewBlock'" ) , 1 )
require . NoError ( t , err )
err = s . Subscribe ( ctx , clientID , query . MustParse ( "tm.events.type='NewBlockHeader'" ) , ch2 )
subscription2 , err : = s . Subscribe ( ctx , clientID , query . MustParse ( "tm.events.type='NewBlockHeader'" ) , 1 )
require . NoError ( t , err )
err = s . UnsubscribeAll ( ctx , clientID )
@ -173,13 +165,15 @@ func TestUnsubscribeAll(t *testing.T) {
err = s . Publish ( ctx , "Nick Fury" )
require . NoError ( t , err )
assert . Zero ( t , len ( ch1 ) , "Should not receive anything after UnsubscribeAll" )
assert . Zero ( t , len ( ch2 ) , "Should not receive anything after UnsubscribeAll" )
assert . Zero ( t , len ( subscription1 . Out ( ) ) , "Should not receive anything after UnsubscribeAll" )
assert . Zero ( t , len ( subscription2 . Out ( ) ) , "Should not receive anything after UnsubscribeAll" )
_ , ok := <- ch1
_ , ok := <- subscription1 . Cancelled ( )
assert . False ( t , ok )
_ , ok = <- ch2
assert . Equal ( t , pubsub . ErrUnsubscribed , subscription1 . Err ( ) )
_ , ok = <- subscription2 . Cancelled ( )
assert . False ( t , ok )
assert . Equal ( t , pubsub . ErrUnsubscribed , subscription2 . Err ( ) )
}
func TestBufferCapacity ( t * testing . T ) {
@ -217,12 +211,20 @@ func benchmarkNClients(n int, b *testing.B) {
ctx := context . Background ( )
for i := 0 ; i < n ; i ++ {
ch := make ( chan interface { } )
subscription , err := s . Subscribe ( ctx , clientID , query . MustParse ( fmt . Sprintf ( "abci.Account.Owner = 'Ivan' AND abci.Invoices.Number = %d" , i ) ) , 1 )
if err != nil {
b . Fatal ( err )
}
go func ( ) {
for range ch {
for {
select {
case <- subscription . Out ( ) :
continue
case <- subscription . Cancelled ( ) :
return
}
}
} ( )
s . Subscribe ( ctx , clientID , query . MustParse ( fmt . Sprintf ( "abci.Account.Owner = 'Ivan' AND abci.Invoices.Number = %d" , i ) ) , ch )
}
b . ReportAllocs ( )
@ -240,12 +242,20 @@ func benchmarkNClientsOneQuery(n int, b *testing.B) {
ctx := context . Background ( )
q := query . MustParse ( "abci.Account.Owner = 'Ivan' AND abci.Invoices.Number = 1" )
for i := 0 ; i < n ; i ++ {
ch := make ( chan interface { } )
subscription , err := s . Subscribe ( ctx , clientID , q , 1 )
if err != nil {
b . Fatal ( err )
}
go func ( ) {
for range ch {
for {
select {
case <- subscription . Out ( ) :
continue
case <- subscription . Cancelled ( ) :
return
}
}
} ( )
s . Subscribe ( ctx , clientID , q , ch )
}
b . ReportAllocs ( )
@ -259,12 +269,10 @@ func benchmarkNClientsOneQuery(n int, b *testing.B) {
/// HELPERS
///////////////////////////////////////////////////////////////////////////////
func assertReceive ( t * testing . T , expected interface { } , ch <- chan interface { } , msgAndArgs ... interface { } ) {
func assertReceive ( t * testing . T , expected interface { } , ch <- chan pubsub . MsgAndTags , msgAndArgs ... interface { } ) {
select {
case actual := <- ch :
if actual != nil {
assert . Equal ( t , expected , actual , msgAndArgs ... )
}
assert . Equal ( t , expected , actual . Msg , msgAndArgs ... )
case <- time . After ( 1 * time . Second ) :
t . Errorf ( "Expected to receive %v from the channel, got nothing after 1s" , expected )
debug . PrintStack ( )