@ -7,43 +7,87 @@ import (
"testing"
"github.com/golang/mock/gomock"
libp2p_peer "github.com/libp2p/go-libp2p-peer"
libp2p_peer "github.com/libp2p/go-libp2p-core/ peer"
libp2p_pubsub "github.com/libp2p/go-libp2p-pubsub"
libp2p_pubsub_pb "github.com/libp2p/go-libp2p-pubsub/pb"
nodeconfig "github.com/harmony-one/harmony/internal/configs/node"
mock "github.com/harmony-one/harmony/p2p/host/hostv2/mock"
)
func TestHostV2_SendMessageToGroups ( t * testing . T ) {
t . Run ( "Basic" , func ( t * testing . T ) {
mc := gomock . NewController ( t )
defer mc . Finish ( )
groups := [ ] nodeconfig . GroupID { "ABC" , "DEF" }
okTopic := NewMocktopicHandle ( mc )
newTopic := NewMocktopicHandle ( mc )
groups := [ ] nodeconfig . GroupID { "OK" , "New" }
data := [ ] byte { 1 , 2 , 3 }
pubsub := mock . NewMockpubsub ( mc )
joined := map [ string ] topicHandle { "OK" : okTopic }
joiner := NewMocktopicJoiner ( mc )
host := & HostV2 { joiner : joiner , joined : joined }
gomock . InOrder (
pubsub . EXPECT ( ) . Publish ( "ABC" , data ) ,
pubsub . EXPECT ( ) . Publish ( "DEF" , data ) ,
// okTopic is already in joined map, JoinTopic shouldn't be called
joiner . EXPECT ( ) . JoinTopic ( "OK" ) . Times ( 0 ) ,
okTopic . EXPECT ( ) . Publish ( context . TODO ( ) , data ) . Return ( nil ) ,
// newTopic is not in joined map, JoinTopic should be called
joiner . EXPECT ( ) . JoinTopic ( "New" ) . Return ( newTopic , nil ) ,
newTopic . EXPECT ( ) . Publish ( context . TODO ( ) , data ) . Return ( nil ) ,
)
host := & HostV2 { pubsub : pubsub }
if err := host . SendMessageToGroups ( groups , data ) ; err != nil {
err := host . SendMessageToGroups ( groups , data )
if err != nil {
t . Errorf ( "expected no error; got %v" , err )
}
} )
t . Run ( "Error" , func ( t * testing . T ) {
t . Run ( "JoinError" , func ( t * testing . T ) {
mc := gomock . NewController ( t )
defer mc . Finish ( )
okTopic := NewMocktopicHandle ( mc )
groups := [ ] nodeconfig . GroupID { "Error" , "OK" }
data := [ ] byte { 1 , 2 , 3 }
joiner := NewMocktopicJoiner ( mc )
host := & HostV2 { joiner : joiner , joined : map [ string ] topicHandle { } }
gomock . InOrder (
// Make first join return an error
joiner . EXPECT ( ) . JoinTopic ( "Error" ) . Return ( nil , errors . New ( "join error" ) ) ,
// Subsequent topics should still be processed after an error
joiner . EXPECT ( ) . JoinTopic ( "OK" ) . Return ( okTopic , nil ) ,
okTopic . EXPECT ( ) . Publish ( context . TODO ( ) , data ) . Return ( nil ) ,
)
err := host . SendMessageToGroups ( groups , data )
if err == nil {
t . Error ( "expected an error; got nil" )
}
} )
t . Run ( "PublishError" , func ( t * testing . T ) {
mc := gomock . NewController ( t )
defer mc . Finish ( )
groups := [ ] nodeconfig . GroupID { "ABC" , "DEF" }
okTopic := NewMocktopicHandle ( mc )
erringTopic := NewMocktopicHandle ( mc )
groups := [ ] nodeconfig . GroupID { "Error" , "OK" }
data := [ ] byte { 1 , 2 , 3 }
pubsub := mock . NewMockpubsub ( mc )
joiner := NewMocktopicJoiner ( mc )
host := & HostV2 { joiner : joiner , joined : map [ string ] topicHandle { } }
gomock . InOrder (
pubsub . EXPECT ( ) . Publish ( "ABC" , data ) . Return ( errors . New ( "FIAL" ) ) ,
pubsub . EXPECT ( ) . Publish ( "DEF" , data ) , // Should not early-return
// Make first publish return an error
joiner . EXPECT ( ) . JoinTopic ( "Error" ) . Return ( erringTopic , nil ) ,
erringTopic . EXPECT ( ) . Publish ( context . TODO ( ) , data ) . Return ( errors . New ( "publish error" ) ) ,
// Subsequent topics should still be processed after an error
joiner . EXPECT ( ) . JoinTopic ( "OK" ) . Return ( okTopic , nil ) ,
okTopic . EXPECT ( ) . Publish ( context . TODO ( ) , data ) . Return ( nil ) ,
)
host := & HostV2 { pubsub : pubsub }
if err := host . SendMessageToGroups ( groups , data ) ; err == nil {
t . Error ( "expected an error but got none" )
t . Error ( "expected an error; got nil " )
}
} )
}
@ -51,10 +95,14 @@ func TestHostV2_SendMessageToGroups(t *testing.T) {
func TestGroupReceiver_Close ( t * testing . T ) {
mc := gomock . NewController ( t )
defer mc . Finish ( )
sub := mock . NewMocksubscription ( mc )
sub := NewMocksubscription ( mc )
sub . EXPECT ( ) . Cancel ( )
receiver := GroupReceiverImpl { sub : sub }
if err := receiver . Close ( ) ; err != nil {
err := receiver . Close ( )
if err != nil {
t . Errorf ( "expected no error but got %v" , err )
}
}
@ -65,46 +113,71 @@ func pubsubMessage(from libp2p_peer.ID, data []byte) *libp2p_pubsub.Message {
}
func TestGroupReceiver_Receive ( t * testing . T ) {
mc := gomock . NewController ( t )
defer mc . Finish ( )
sub := mock . NewMocksubscription ( mc )
ctx := context . Background ( )
gomock . InOrder (
sub . EXPECT ( ) . Next ( ctx ) . Return ( pubsubMessage ( "ABC" , [ ] byte { 1 , 2 , 3 } ) , nil ) ,
sub . EXPECT ( ) . Next ( ctx ) . Return ( pubsubMessage ( "DEF" , [ ] byte { 4 , 5 , 6 } ) , nil ) ,
sub . EXPECT ( ) . Next ( ctx ) . Return ( nil , errors . New ( "FIAL" ) ) ,
)
receiver := GroupReceiverImpl { sub : sub }
verify := func ( sender libp2p_peer . ID , msg [ ] byte , shouldError bool ) {
t . Run ( "OK" , func ( t * testing . T ) {
mc := gomock . NewController ( t )
defer mc . Finish ( )
ctx := context . Background ( )
sub := NewMocksubscription ( mc )
receiver := GroupReceiverImpl { sub : sub }
wantSender := libp2p_peer . ID ( "OK" )
wantMsg := [ ] byte { 1 , 2 , 3 }
sub . EXPECT ( ) . Next ( ctx ) . Return ( pubsubMessage ( wantSender , wantMsg ) , nil )
gotMsg , gotSender , err := receiver . Receive ( ctx )
if ( err != nil ) != shouldError {
if shouldError {
t . Error ( "expected an error but got none" )
} else {
t . Errorf ( "expected no error but got %v" , err )
}
if err != nil {
t . Errorf ( "expected no error; got %v" , err )
}
if gotSender != s ender {
t . Errorf ( "expected sender %v but got %v" , s ender , gotSender )
if gotSender != wantSender {
t . Errorf ( "expected sender %v; got %v" , wantSender , gotSender )
}
if ! reflect . DeepEqual ( gotMsg , m sg) {
t . Errorf ( "expected message %v but got %v" , m sg , gotMsg )
if ! reflect . DeepEqual ( gotMsg , wantM sg) {
t . Errorf ( "expected message %v; got %v" , wantM sg , gotMsg )
}
}
verify ( "ABC" , [ ] byte { 1 , 2 , 3 } , false )
verify ( "DEF" , [ ] byte { 4 , 5 , 6 } , false )
verify ( "" , nil , true )
} )
t . Run ( "Error" , func ( t * testing . T ) {
mc := gomock . NewController ( t )
defer mc . Finish ( )
ctx := context . Background ( )
sub := NewMocksubscription ( mc )
receiver := GroupReceiverImpl { sub : sub }
sub . EXPECT ( ) . Next ( ctx ) . Return ( nil , errors . New ( "receive error" ) )
msg , sender , err := receiver . Receive ( ctx )
if err == nil {
t . Error ( "expected an error; got nil" )
}
if sender != "" {
t . Errorf ( "expected empty sender; got %v" , sender )
}
if len ( msg ) > 0 {
t . Errorf ( "expected empty message; got %v" , msg )
}
} )
}
func TestHostV2_GroupReceiver ( t * testing . T ) {
t . Run ( "Basic" , func ( t * testing . T ) {
t . Run ( "New " , func ( t * testing . T ) {
mc := gomock . NewController ( t )
defer mc . Finish ( )
sub := & libp2p_pubsub . Subscription { }
pubsub := mock . NewMockpubsub ( mc )
pubsub . EXPECT ( ) . Subscribe ( "ABC" ) . Return ( sub , nil )
host := & HostV2 { pubsub : pubsub }
topic := NewMocktopicHandle ( mc )
joiner := NewMocktopicJoiner ( mc )
host := & HostV2 { joiner : joiner , joined : map [ string ] topicHandle { } }
gomock . InOrder (
joiner . EXPECT ( ) . JoinTopic ( "ABC" ) . Return ( topic , nil ) ,
topic . EXPECT ( ) . Subscribe ( ) . Return ( sub , nil ) ,
)
gotReceiver , err := host . GroupReceiver ( "ABC" )
if r , ok := gotReceiver . ( * GroupReceiverImpl ) ; ! ok {
t . Errorf ( "expected a hostv2 GroupReceiverImpl; got %v" , gotReceiver )
} else if r . sub != sub {
@ -114,13 +187,39 @@ func TestHostV2_GroupReceiver(t *testing.T) {
t . Errorf ( "expected no error; got %v" , err )
}
} )
t . Run ( "Error" , func ( t * testing . T ) {
t . Run ( "JoinError" , func ( t * testing . T ) {
mc := gomock . NewController ( t )
defer mc . Finish ( )
joiner := NewMocktopicJoiner ( mc )
host := & HostV2 { joiner : joiner , joined : map [ string ] topicHandle { } }
joiner . EXPECT ( ) . JoinTopic ( "ABC" ) . Return ( nil , errors . New ( "join error" ) )
gotReceiver , err := host . GroupReceiver ( "ABC" )
if gotReceiver != nil {
t . Errorf ( "expected a nil hostv2 GroupReceiverImpl; got %v" , gotReceiver )
}
if err == nil {
t . Error ( "expected an error; got none" )
}
} )
t . Run ( "SubscribeError" , func ( t * testing . T ) {
mc := gomock . NewController ( t )
defer mc . Finish ( )
pubsub := mock . NewMockpubsub ( mc )
pubsub . EXPECT ( ) . Subscribe ( "ABC" ) . Return ( nil , errors . New ( "FIAL" ) )
host := & HostV2 { pubsub : pubsub }
topic := NewMocktopicHandle ( mc )
joiner := NewMocktopicJoiner ( mc )
host := & HostV2 { joiner : joiner , joined : map [ string ] topicHandle { } }
gomock . InOrder (
joiner . EXPECT ( ) . JoinTopic ( "ABC" ) . Return ( topic , nil ) ,
topic . EXPECT ( ) . Subscribe ( ) . Return ( nil , errors . New ( "subscription error" ) ) ,
)
gotReceiver , err := host . GroupReceiver ( "ABC" )
if gotReceiver != nil {
t . Errorf ( "expected a nil hostv2 GroupReceiverImpl; got %v" , gotReceiver )
}
@ -136,3 +235,65 @@ func TestHostV2_GroupReceiver(t *testing.T) {
}
} )
}
func TestHostV2_getTopic ( t * testing . T ) {
t . Run ( "NewOK" , func ( t * testing . T ) {
mc := gomock . NewController ( t )
defer mc . Finish ( )
joiner := NewMocktopicJoiner ( mc )
want := NewMocktopicHandle ( mc )
host := & HostV2 { joiner : joiner , joined : map [ string ] topicHandle { } }
joiner . EXPECT ( ) . JoinTopic ( "ABC" ) . Return ( want , nil )
got , err := host . getTopic ( "ABC" )
if err != nil {
t . Errorf ( "want nil error; got %v" , err )
}
if got != want {
t . Errorf ( "want topic handle %v; got %v" , want , got )
}
if _ , ok := host . joined [ "ABC" ] ; ! ok {
t . Error ( "topic not found in joined map" )
}
} )
t . Run ( "NewError" , func ( t * testing . T ) {
mc := gomock . NewController ( t )
defer mc . Finish ( )
joiner := NewMocktopicJoiner ( mc )
host := & HostV2 { joiner : joiner , joined : map [ string ] topicHandle { } }
joiner . EXPECT ( ) . JoinTopic ( "ABC" ) . Return ( nil , errors . New ( "OMG" ) )
got , err := host . getTopic ( "ABC" )
if err == nil {
t . Error ( "want non-nil error; got nil" )
}
if got != nil {
t . Errorf ( "want nil handle; got %v" , got )
}
} )
t . Run ( "Existing" , func ( t * testing . T ) {
mc := gomock . NewController ( t )
defer mc . Finish ( )
joiner := NewMocktopicJoiner ( mc )
want := NewMocktopicHandle ( mc )
host := & HostV2 { joiner : joiner , joined : map [ string ] topicHandle { "ABC" : want } }
joiner . EXPECT ( ) . JoinTopic ( "ABC" ) . Times ( 0 )
got , err := host . getTopic ( "ABC" )
if err != nil {
t . Errorf ( "want nil error; got %v" , err )
}
if got != want {
t . Errorf ( "want topic handle %v; got %v" , want , got )
}
} )
}