diff --git a/gossipsub_test.go b/gossipsub_test.go index fde48b8..a2c1c84 100644 --- a/gossipsub_test.go +++ b/gossipsub_test.go @@ -1183,6 +1183,92 @@ func TestGossipsubDirectPeers(t *testing.T) { } } +func TestGossipsubDirectPeersFanout(t *testing.T) { + // regression test for #371 + ctx, cancel := context.WithCancel(context.Background()) + defer cancel() + + h := getNetHosts(t, ctx, 3) + psubs := []*PubSub{ + getGossipsub(ctx, h[0]), + getGossipsub(ctx, h[1], WithDirectPeers([]peer.AddrInfo{peer.AddrInfo{h[2].ID(), h[2].Addrs()}})), + getGossipsub(ctx, h[2], WithDirectPeers([]peer.AddrInfo{peer.AddrInfo{h[1].ID(), h[1].Addrs()}})), + } + + connect(t, h[0], h[1]) + connect(t, h[0], h[2]) + + // Join all peers except h2 + var subs []*Subscription + for _, ps := range psubs[:2] { + sub, err := ps.Subscribe("test") + if err != nil { + t.Fatal(err) + } + subs = append(subs, sub) + } + + time.Sleep(time.Second) + + // h2 publishes some messages to build a fanout + for i := 0; i < 3; i++ { + msg := []byte(fmt.Sprintf("message %d", i)) + psubs[2].Publish("test", msg) + + for _, sub := range subs { + assertReceive(t, sub, msg) + } + } + + // verify that h0 is in the fanout of h2, but not h1 who is a direct peer + result := make(chan bool, 2) + psubs[2].eval <- func() { + rt := psubs[2].rt.(*GossipSubRouter) + fanout := rt.fanout["test"] + _, ok := fanout[h[0].ID()] + result <- ok + _, ok = fanout[h[1].ID()] + result <- ok + } + + inFanout := <-result + if !inFanout { + t.Fatal("expected peer 0 to be in fanout") + } + + inFanout = <-result + if inFanout { + t.Fatal("expected peer 1 to not be in fanout") + } + + // now subscribe h2 too and verify tht h0 is in the mesh but not h1 + _, err := psubs[2].Subscribe("test") + if err != nil { + t.Fatal(err) + } + + time.Sleep(2 * time.Second) + + psubs[2].eval <- func() { + rt := psubs[2].rt.(*GossipSubRouter) + mesh := rt.mesh["test"] + _, ok := mesh[h[0].ID()] + result <- ok + _, ok = mesh[h[1].ID()] + result <- ok + } + + inMesh := <-result + if !inMesh { + t.Fatal("expected peer 0 to be in mesh") + } + + inMesh = <-result + if inMesh { + t.Fatal("expected peer 1 to not be in mesh") + } +} + func TestGossipsubFloodPublish(t *testing.T) { // uses a star topology without PX and publishes from the star to verify that all // messages get received