mirror of https://github.com/status-im/go-waku.git
223 lines
5.5 KiB
Go
223 lines
5.5 KiB
Go
package subscription
|
|
|
|
import (
|
|
"context"
|
|
"sync"
|
|
"testing"
|
|
"time"
|
|
|
|
"github.com/libp2p/go-libp2p/core/peer"
|
|
"github.com/libp2p/go-libp2p/core/test"
|
|
"github.com/stretchr/testify/assert"
|
|
"github.com/stretchr/testify/require"
|
|
"github.com/waku-org/go-waku/tests"
|
|
"github.com/waku-org/go-waku/waku/v2/protocol"
|
|
"github.com/waku-org/go-waku/waku/v2/utils"
|
|
"google.golang.org/protobuf/proto"
|
|
)
|
|
|
|
const PUBSUB_TOPIC = "/test/topic"
|
|
|
|
func createPeerID(t *testing.T) peer.ID {
|
|
peerId, err := test.RandPeerID()
|
|
assert.NoError(t, err)
|
|
return peerId
|
|
}
|
|
|
|
func TestSubscriptionMapAppend(t *testing.T) {
|
|
fmap := NewSubscriptionMap(utils.Logger())
|
|
peerID := createPeerID(t)
|
|
contentTopics := protocol.NewContentTopicSet("ct1", "ct2")
|
|
|
|
sub := fmap.NewSubscription(peerID, protocol.ContentFilter{PubsubTopic: PUBSUB_TOPIC, ContentTopics: contentTopics})
|
|
_, found := sub.ContentFilter.ContentTopics["ct1"]
|
|
require.True(t, found)
|
|
_, found = sub.ContentFilter.ContentTopics["ct2"]
|
|
require.True(t, found)
|
|
require.False(t, sub.Closed)
|
|
require.Equal(t, sub.PeerID, peerID)
|
|
require.Equal(t, sub.ContentFilter.PubsubTopic, PUBSUB_TOPIC)
|
|
|
|
sub.Add("ct3")
|
|
_, found = sub.ContentFilter.ContentTopics["ct3"]
|
|
require.True(t, found)
|
|
|
|
sub.Remove("ct3")
|
|
_, found = sub.ContentFilter.ContentTopics["ct3"]
|
|
require.False(t, found)
|
|
|
|
err := sub.Close()
|
|
require.NoError(t, err)
|
|
require.True(t, sub.Closed)
|
|
|
|
err = sub.Close()
|
|
require.NoError(t, err)
|
|
}
|
|
|
|
func TestSubscriptionClear(t *testing.T) {
|
|
fmap := NewSubscriptionMap(utils.Logger())
|
|
contentTopics := protocol.NewContentTopicSet("ct1", "ct2")
|
|
|
|
var subscriptions = []*SubscriptionDetails{
|
|
fmap.NewSubscription(createPeerID(t), protocol.ContentFilter{PubsubTopic: PUBSUB_TOPIC + "1", ContentTopics: contentTopics}),
|
|
fmap.NewSubscription(createPeerID(t), protocol.ContentFilter{PubsubTopic: PUBSUB_TOPIC + "2", ContentTopics: contentTopics}),
|
|
fmap.NewSubscription(createPeerID(t), protocol.ContentFilter{PubsubTopic: PUBSUB_TOPIC + "3", ContentTopics: contentTopics}),
|
|
}
|
|
|
|
ctx, cancel := context.WithTimeout(context.Background(), 3*time.Second)
|
|
defer cancel()
|
|
|
|
wg := sync.WaitGroup{}
|
|
wg.Add(len(subscriptions))
|
|
for _, s := range subscriptions {
|
|
go func(s *SubscriptionDetails) {
|
|
defer wg.Done()
|
|
select {
|
|
case <-ctx.Done():
|
|
t.Fail()
|
|
return
|
|
case <-s.C:
|
|
return
|
|
}
|
|
}(s)
|
|
}
|
|
|
|
fmap.Clear()
|
|
|
|
wg.Wait()
|
|
|
|
require.True(t, subscriptions[0].Closed)
|
|
require.True(t, subscriptions[1].Closed)
|
|
require.True(t, subscriptions[2].Closed)
|
|
}
|
|
|
|
func TestSubscriptionsNotify(t *testing.T) {
|
|
fmap := NewSubscriptionMap(utils.Logger())
|
|
p1 := createPeerID(t)
|
|
p2 := createPeerID(t)
|
|
var subscriptions = []*SubscriptionDetails{
|
|
fmap.NewSubscription(p1, protocol.ContentFilter{PubsubTopic: PUBSUB_TOPIC + "1", ContentTopics: protocol.NewContentTopicSet("ct1", "ct2")}),
|
|
fmap.NewSubscription(p2, protocol.ContentFilter{PubsubTopic: PUBSUB_TOPIC + "1", ContentTopics: protocol.NewContentTopicSet("ct1")}),
|
|
fmap.NewSubscription(p1, protocol.ContentFilter{PubsubTopic: PUBSUB_TOPIC + "2", ContentTopics: protocol.NewContentTopicSet("ct1", "ct2")}),
|
|
}
|
|
|
|
ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
|
|
successChan := make(chan struct{}, 10)
|
|
wg := sync.WaitGroup{}
|
|
|
|
successOnReceive := func(ctx context.Context, i int) {
|
|
defer wg.Done()
|
|
|
|
if subscriptions[i].Closed {
|
|
successChan <- struct{}{}
|
|
return
|
|
}
|
|
|
|
select {
|
|
case <-ctx.Done():
|
|
panic("should have failed1")
|
|
case c := <-subscriptions[i].C:
|
|
if c == nil {
|
|
panic("should have failed2")
|
|
}
|
|
successChan <- struct{}{}
|
|
return
|
|
}
|
|
}
|
|
|
|
failOnReceive := func(ctx context.Context, i int) {
|
|
defer wg.Done()
|
|
|
|
if subscriptions[i].Closed {
|
|
successChan <- struct{}{}
|
|
return
|
|
}
|
|
|
|
select {
|
|
case <-ctx.Done():
|
|
successChan <- struct{}{}
|
|
return
|
|
case c := <-subscriptions[i].C:
|
|
if c != nil {
|
|
panic("should have failed")
|
|
}
|
|
successChan <- struct{}{}
|
|
return
|
|
}
|
|
}
|
|
|
|
wg.Add(3)
|
|
go successOnReceive(ctx, 0)
|
|
go successOnReceive(ctx, 1)
|
|
go failOnReceive(ctx, 2)
|
|
time.Sleep(200 * time.Millisecond)
|
|
|
|
envTopic1Ct1 := protocol.NewEnvelope(tests.CreateWakuMessage("ct1", nil), 0, PUBSUB_TOPIC+"1")
|
|
wg.Add(1)
|
|
go func() {
|
|
defer wg.Done()
|
|
fmap.Notify(p1, envTopic1Ct1)
|
|
fmap.Notify(p2, envTopic1Ct1)
|
|
}()
|
|
|
|
<-successChan
|
|
<-successChan
|
|
cancel()
|
|
wg.Wait()
|
|
<-successChan
|
|
|
|
//////////////////////////////////////
|
|
|
|
ctx, cancel = context.WithTimeout(context.Background(), 5*time.Second)
|
|
|
|
wg.Add(3)
|
|
go successOnReceive(ctx, 0)
|
|
go failOnReceive(ctx, 1)
|
|
go failOnReceive(ctx, 2)
|
|
time.Sleep(200 * time.Millisecond)
|
|
|
|
envTopic1Ct2 := protocol.NewEnvelope(tests.CreateWakuMessage("ct2", nil), 0, PUBSUB_TOPIC+"1")
|
|
wg.Add(1)
|
|
go func() {
|
|
defer wg.Done()
|
|
fmap.Notify(p1, envTopic1Ct2)
|
|
fmap.Notify(p2, envTopic1Ct2)
|
|
}()
|
|
|
|
<-successChan
|
|
cancel()
|
|
wg.Wait()
|
|
<-successChan
|
|
<-successChan
|
|
|
|
//////////////////////////////////////
|
|
|
|
// Testing after closing the subscription
|
|
|
|
subscriptions[0].Close()
|
|
time.Sleep(200 * time.Millisecond)
|
|
|
|
ctx, cancel = context.WithTimeout(context.Background(), 5*time.Second)
|
|
|
|
wg.Add(3)
|
|
go failOnReceive(ctx, 0)
|
|
go successOnReceive(ctx, 1)
|
|
go failOnReceive(ctx, 2)
|
|
time.Sleep(200 * time.Millisecond)
|
|
|
|
envTopic1Ct1_2 := protocol.NewEnvelope(tests.CreateWakuMessage("ct1", proto.Int64(1)), 1, PUBSUB_TOPIC+"1")
|
|
|
|
wg.Add(1)
|
|
go func() {
|
|
defer wg.Done()
|
|
fmap.Notify(p1, envTopic1Ct1_2)
|
|
fmap.Notify(p2, envTopic1Ct1_2)
|
|
}()
|
|
|
|
<-successChan // One of these successes is for closing the subscription
|
|
<-successChan
|
|
cancel()
|
|
wg.Wait()
|
|
<-successChan
|
|
}
|