diff --git a/score_test.go b/score_test.go index 82d98fdd..8e04a208 100644 --- a/score_test.go +++ b/score_test.go @@ -842,6 +842,103 @@ func TestScoreRetention(t *testing.T) { } } +func TestScoreResetTopicParams(t *testing.T) { + // Create parameters with reasonable default values + mytopic := "mytopic" + params := &PeerScoreParams{ + AppSpecificScore: func(peer.ID) float64 { return 0 }, + Topics: make(map[string]*TopicScoreParams), + } + topicScoreParams := &TopicScoreParams{ + TopicWeight: 1, + + MeshMessageDeliveriesWeight: -1, + MeshMessageDeliveriesActivation: time.Second, + MeshMessageDeliveriesWindow: 10 * time.Millisecond, + MeshMessageDeliveriesThreshold: 20, + MeshMessageDeliveriesCap: 100, + MeshMessageDeliveriesDecay: 1.0, // no decay for this test + + FirstMessageDeliveriesWeight: 10, + FirstMessageDeliveriesDecay: 1.0, // no decay for this test + FirstMessageDeliveriesCap: 100, + + TimeInMeshQuantum: time.Second, + } + + params.Topics[mytopic] = topicScoreParams + + // peer A always delivers the message first. + // peer B delivers next (within the delivery window). + // peer C delivers outside the delivery window. + // we expect peers A and B to have a score of zero, since all other parameter weights are zero. + // Peer C should have a negative score. + peerA := peer.ID("A") + peerB := peer.ID("B") + peers := []peer.ID{peerA, peerB} + + ps := newPeerScore(params) + for _, p := range peers { + ps.AddPeer(p, "myproto") + ps.Graft(p, mytopic) + } + + // deliver a bunch of messages from peer A, with duplicates within the window from peer B, + nMessages := 100 + for i := 0; i < nMessages; i++ { + pbMsg := makeTestMessage(i) + pbMsg.TopicIDs = []string{mytopic} + msg := Message{ReceivedFrom: peerA, Message: pbMsg} + ps.ValidateMessage(&msg) + ps.DeliverMessage(&msg) + + msg.ReceivedFrom = peerB + ps.DuplicateMessage(&msg) + } + + // check that the FirstMessageDeliveries for peerA and MeshMessageDeliveries for PeerB is + // at 100 + if ps.peerStats[peerA].topics[mytopic].firstMessageDeliveries != 100 { + t.Fatalf("expected 100 FirstMessageDeliveries for peerA, but got %f", ps.peerStats[peerA].topics[mytopic].firstMessageDeliveries) + } + // check that the MeshMessageDeliveries for peerB and MeshMessageDeliveries for PeerB is + // at 100 + if ps.peerStats[peerB].topics[mytopic].meshMessageDeliveries != 100 { + t.Fatalf("expected 100 MeshMessageDeliveries for peerB, but got %f", ps.peerStats[peerB].topics[mytopic].meshMessageDeliveries) + } + + // reset the topic paramaters recapping the deliveries counters + newTopicScoreParams := &TopicScoreParams{ + TopicWeight: 1, + + MeshMessageDeliveriesWeight: -1, + MeshMessageDeliveriesActivation: time.Second, + MeshMessageDeliveriesWindow: 10 * time.Millisecond, + MeshMessageDeliveriesThreshold: 20, + MeshMessageDeliveriesCap: 50, + MeshMessageDeliveriesDecay: 1.0, // no decay for this test + + FirstMessageDeliveriesWeight: 10, + FirstMessageDeliveriesDecay: 1.0, // no decay for this test + FirstMessageDeliveriesCap: 50, + + TimeInMeshQuantum: time.Second, + } + + err := ps.SetTopicScoreParams(mytopic, newTopicScoreParams) + if err != nil { + t.Fatal(err) + } + + // verify that the counters got recapped + if ps.peerStats[peerA].topics[mytopic].firstMessageDeliveries != 50 { + t.Fatalf("expected 50 FirstMessageDeliveries for peerA, but got %f", ps.peerStats[peerA].topics[mytopic].firstMessageDeliveries) + } + if ps.peerStats[peerB].topics[mytopic].meshMessageDeliveries != 50 { + t.Fatalf("expected 50 MeshMessageDeliveries for peerB, but got %f", ps.peerStats[peerB].topics[mytopic].meshMessageDeliveries) + } +} + func withinVariance(score float64, expected float64, variance float64) bool { if expected >= 0 { return score > expected*(1-variance) && score < expected*(1+variance)