From 2bfdcb6fd16ec4f92f539706701a7bc208a29cff Mon Sep 17 00:00:00 2001 From: Nicholas Molnar <65710+neekolas@users.noreply.github.com> Date: Tue, 26 Jul 2022 12:20:56 -0700 Subject: [PATCH] fix: handle case of unsubscribe from non-existent topic (#276) --- waku/v2/protocol/filter/filter_subscribers.go | 9 +- .../filter/filter_subscribers_test.go | 91 +++++++++++++++++++ 2 files changed, 96 insertions(+), 4 deletions(-) create mode 100644 waku/v2/protocol/filter/filter_subscribers_test.go diff --git a/waku/v2/protocol/filter/filter_subscribers.go b/waku/v2/protocol/filter/filter_subscribers.go index fdfd7389..d83036e2 100644 --- a/waku/v2/protocol/filter/filter_subscribers.go +++ b/waku/v2/protocol/filter/filter_subscribers.go @@ -120,22 +120,23 @@ func (sub *Subscribers) RemoveContentFilters(peerID peer.ID, contentFilters []*p var peerIdsToRemove []peer.ID - for _, subscriber := range sub.subscribers { + for subIndex, subscriber := range sub.subscribers { if subscriber.peer != peerID { continue } // make sure we delete the content filter // if no more topics are left - for i, contentFilter := range contentFilters { + for _, contentFilter := range contentFilters { subCfs := subscriber.filter.ContentFilters - for _, cf := range subCfs { + for i, cf := range subCfs { if cf.ContentTopic == contentFilter.ContentTopic { l := len(subCfs) - 1 - subCfs[l], subCfs[i] = subCfs[i], subCfs[l] + subCfs[i] = subCfs[l] subscriber.filter.ContentFilters = subCfs[:l] } } + sub.subscribers[subIndex] = subscriber } if len(subscriber.filter.ContentFilters) == 0 { diff --git a/waku/v2/protocol/filter/filter_subscribers_test.go b/waku/v2/protocol/filter/filter_subscribers_test.go new file mode 100644 index 00000000..fa924f06 --- /dev/null +++ b/waku/v2/protocol/filter/filter_subscribers_test.go @@ -0,0 +1,91 @@ +package filter + +import ( + "testing" + "time" + + "github.com/libp2p/go-libp2p-core/peer" + "github.com/libp2p/go-libp2p-core/test" + "github.com/status-im/go-waku/waku/v2/protocol/pb" + "github.com/stretchr/testify/assert" +) + +const TOPIC = "/test/topic" + +func createPeerId(t *testing.T) peer.ID { + peerId, err := test.RandPeerID() + assert.NoError(t, err) + return peerId +} + +func firstSubscriber(subs *Subscribers, contentTopic string) *Subscriber { + for sub := range subs.Items(&contentTopic) { + return &sub + } + return nil +} + +func TestAppend(t *testing.T) { + subs := NewSubscribers(10 * time.Second) + peerId := createPeerId(t) + contentTopic := "topic1" + request := pb.FilterRequest{ + Subscribe: true, + Topic: TOPIC, + ContentFilters: []*pb.FilterRequest_ContentFilter{{ContentTopic: contentTopic}}, + } + subs.Append(Subscriber{peerId, "request_1", request}) + + sub := firstSubscriber(subs, contentTopic) + assert.NotNil(t, sub) +} + +func TestRemove(t *testing.T) { + subs := NewSubscribers(10 * time.Second) + peerId := createPeerId(t) + contentTopic := "topic1" + request := pb.FilterRequest{ + Subscribe: true, + Topic: TOPIC, + ContentFilters: []*pb.FilterRequest_ContentFilter{{ContentTopic: contentTopic}}, + } + subs.Append(Subscriber{peerId, "request_1", request}) + subs.RemoveContentFilters(peerId, request.ContentFilters) + + sub := firstSubscriber(subs, contentTopic) + assert.Nil(t, sub) +} + +func TestRemovePartial(t *testing.T) { + subs := NewSubscribers(10 * time.Second) + peerId := createPeerId(t) + topic1 := "topic1" + topic2 := "topic2" + request := pb.FilterRequest{ + Subscribe: true, + Topic: TOPIC, + ContentFilters: []*pb.FilterRequest_ContentFilter{{ContentTopic: topic1}, {ContentTopic: topic2}}, + } + subs.Append(Subscriber{peerId, "request_1", request}) + subs.RemoveContentFilters(peerId, []*pb.FilterRequest_ContentFilter{{ContentTopic: topic1}}) + + sub := firstSubscriber(subs, topic2) + assert.NotNil(t, sub) + assert.Len(t, sub.filter.ContentFilters, 1) +} + +func TestRemoveBogus(t *testing.T) { + subs := NewSubscribers(10 * time.Second) + peerId := createPeerId(t) + contentTopic := "topic1" + request := pb.FilterRequest{ + Subscribe: true, + Topic: TOPIC, + ContentFilters: []*pb.FilterRequest_ContentFilter{{ContentTopic: contentTopic}}, + } + subs.Append(Subscriber{peerId, "request_1", request}) + subs.RemoveContentFilters(peerId, []*pb.FilterRequest_ContentFilter{{ContentTopic: "does not exist"}, {ContentTopic: contentTopic}}) + + sub := firstSubscriber(subs, contentTopic) + assert.Nil(t, sub) +}