mirror of
https://github.com/logos-messaging/go-libp2p-pubsub.git
synced 2026-01-07 15:23:08 +00:00
Enables non-atomic validation for peer scoring parameters (#499)
* decouples topic scoring parameters * adds skiping atomic validation for topic parameters * cleans up * adds skip atomic validation to peer score threshold * adds skip atomic validation for peer parameters * adds test for non-atomic validation * adds tests for peer score * adds tests for peer score thresholds * refactors tests
This commit is contained in:
parent
4f56e8f0a7
commit
8866ca88a1
219
score_params.go
219
score_params.go
@ -10,7 +10,10 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
type PeerScoreThresholds struct {
|
type PeerScoreThresholds struct {
|
||||||
// GossipThreshold is the score threshold below which gossip propagation is supressed;
|
// whether it is allowed to just set some params and not all of them.
|
||||||
|
SkipAtomicValidation bool
|
||||||
|
|
||||||
|
// GossipThreshold is the score threshold below which gossip propagation is suppressed;
|
||||||
// should be negative.
|
// should be negative.
|
||||||
GossipThreshold float64
|
GossipThreshold float64
|
||||||
|
|
||||||
@ -18,8 +21,8 @@ type PeerScoreThresholds struct {
|
|||||||
// publishing (also applies to fanout and floodsub peers); should be negative and <= GossipThreshold.
|
// publishing (also applies to fanout and floodsub peers); should be negative and <= GossipThreshold.
|
||||||
PublishThreshold float64
|
PublishThreshold float64
|
||||||
|
|
||||||
// GraylistThreshold is the score threshold below which message processing is supressed altogether,
|
// GraylistThreshold is the score threshold below which message processing is suppressed altogether,
|
||||||
// implementing an effective graylist according to peer score; should be negative and <= PublisThreshold.
|
// implementing an effective gray list according to peer score; should be negative and <= PublishThreshold.
|
||||||
GraylistThreshold float64
|
GraylistThreshold float64
|
||||||
|
|
||||||
// AcceptPXThreshold is the score threshold below which PX will be ignored; this should be positive
|
// AcceptPXThreshold is the score threshold below which PX will be ignored; this should be positive
|
||||||
@ -32,25 +35,38 @@ type PeerScoreThresholds struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (p *PeerScoreThresholds) validate() error {
|
func (p *PeerScoreThresholds) validate() error {
|
||||||
if p.GossipThreshold > 0 || isInvalidNumber(p.GossipThreshold) {
|
|
||||||
return fmt.Errorf("invalid gossip threshold; it must be <= 0 and a valid number")
|
if !p.SkipAtomicValidation || p.PublishThreshold != 0 || p.GossipThreshold != 0 || p.GraylistThreshold != 0 {
|
||||||
|
if p.GossipThreshold > 0 || isInvalidNumber(p.GossipThreshold) {
|
||||||
|
return fmt.Errorf("invalid gossip threshold; it must be <= 0 and a valid number")
|
||||||
|
}
|
||||||
|
if p.PublishThreshold > 0 || p.PublishThreshold > p.GossipThreshold || isInvalidNumber(p.PublishThreshold) {
|
||||||
|
return fmt.Errorf("invalid publish threshold; it must be <= 0 and <= gossip threshold and a valid number")
|
||||||
|
}
|
||||||
|
if p.GraylistThreshold > 0 || p.GraylistThreshold > p.PublishThreshold || isInvalidNumber(p.GraylistThreshold) {
|
||||||
|
return fmt.Errorf("invalid graylist threshold; it must be <= 0 and <= publish threshold and a valid number")
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if p.PublishThreshold > 0 || p.PublishThreshold > p.GossipThreshold || isInvalidNumber(p.PublishThreshold) {
|
|
||||||
return fmt.Errorf("invalid publish threshold; it must be <= 0 and <= gossip threshold and a valid number")
|
if !p.SkipAtomicValidation || p.AcceptPXThreshold != 0 {
|
||||||
|
if p.AcceptPXThreshold < 0 || isInvalidNumber(p.AcceptPXThreshold) {
|
||||||
|
return fmt.Errorf("invalid accept PX threshold; it must be >= 0 and a valid number")
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if p.GraylistThreshold > 0 || p.GraylistThreshold > p.PublishThreshold || isInvalidNumber(p.GraylistThreshold) {
|
|
||||||
return fmt.Errorf("invalid graylist threshold; it must be <= 0 and <= publish threshold and a valid number")
|
if !p.SkipAtomicValidation || p.OpportunisticGraftThreshold != 0 {
|
||||||
}
|
if p.OpportunisticGraftThreshold < 0 || isInvalidNumber(p.OpportunisticGraftThreshold) {
|
||||||
if p.AcceptPXThreshold < 0 || isInvalidNumber(p.AcceptPXThreshold) {
|
return fmt.Errorf("invalid opportunistic grafting threshold; it must be >= 0 and a valid number")
|
||||||
return fmt.Errorf("invalid accept PX threshold; it must be >= 0 and a valid number")
|
}
|
||||||
}
|
|
||||||
if p.OpportunisticGraftThreshold < 0 || isInvalidNumber(p.OpportunisticGraftThreshold) {
|
|
||||||
return fmt.Errorf("invalid opportunistic grafting threshold; it must be >= 0 and a valid number")
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
type PeerScoreParams struct {
|
type PeerScoreParams struct {
|
||||||
|
// whether it is allowed to just set some params and not all of them.
|
||||||
|
SkipAtomicValidation bool
|
||||||
|
|
||||||
// Score parameters per topic.
|
// Score parameters per topic.
|
||||||
Topics map[string]*TopicScoreParams
|
Topics map[string]*TopicScoreParams
|
||||||
|
|
||||||
@ -99,12 +115,15 @@ type PeerScoreParams struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
type TopicScoreParams struct {
|
type TopicScoreParams struct {
|
||||||
|
// whether it is allowed to just set some params and not all of them.
|
||||||
|
SkipAtomicValidation bool
|
||||||
|
|
||||||
// The weight of the topic.
|
// The weight of the topic.
|
||||||
TopicWeight float64
|
TopicWeight float64
|
||||||
|
|
||||||
// P1: time in the mesh
|
// P1: time in the mesh
|
||||||
// This is the time the peer has ben grafted in the mesh.
|
// This is the time the peer has been grafted in the mesh.
|
||||||
// The value of of the parameter is the time/TimeInMeshQuantum, capped by TimeInMeshCap
|
// The value of the parameter is the time/TimeInMeshQuantum, capped by TimeInMeshCap.
|
||||||
// The weight of the parameter MUST be positive (or zero to disable).
|
// The weight of the parameter MUST be positive (or zero to disable).
|
||||||
TimeInMeshWeight float64
|
TimeInMeshWeight float64
|
||||||
TimeInMeshQuantum time.Duration
|
TimeInMeshQuantum time.Duration
|
||||||
@ -124,7 +143,7 @@ type TopicScoreParams struct {
|
|||||||
// when validation succeeds.
|
// when validation succeeds.
|
||||||
// This window accounts for the minimum time before a hostile mesh peer trying to game the score
|
// This window accounts for the minimum time before a hostile mesh peer trying to game the score
|
||||||
// could replay back a valid message we just sent them.
|
// could replay back a valid message we just sent them.
|
||||||
// It effectively tracks first and near-first deliveries, ie a message seen from a mesh peer
|
// It effectively tracks first and near-first deliveries, i.e., a message seen from a mesh peer
|
||||||
// before we have forwarded it to them.
|
// before we have forwarded it to them.
|
||||||
// The parameter has an associated counter, decaying with MeshMessageDeliveriesDecay.
|
// The parameter has an associated counter, decaying with MeshMessageDeliveriesDecay.
|
||||||
// If the counter exceeds the threshold, its value is 0.
|
// If the counter exceeds the threshold, its value is 0.
|
||||||
@ -159,41 +178,55 @@ func (p *PeerScoreParams) validate() error {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// check that the topic score is 0 or something positive
|
if !p.SkipAtomicValidation || p.TopicScoreCap != 0 {
|
||||||
if p.TopicScoreCap < 0 || isInvalidNumber(p.TopicScoreCap) {
|
// check that the topic score is 0 or something positive
|
||||||
return fmt.Errorf("invalid topic score cap; must be positive (or 0 for no cap) and a valid number")
|
if p.TopicScoreCap < 0 || isInvalidNumber(p.TopicScoreCap) {
|
||||||
|
return fmt.Errorf("invalid topic score cap; must be positive (or 0 for no cap) and a valid number")
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// check that we have an app specific score; the weight can be anything (but expected positive)
|
// check that we have an app specific score; the weight can be anything (but expected positive)
|
||||||
if p.AppSpecificScore == nil {
|
if p.AppSpecificScore == nil {
|
||||||
return fmt.Errorf("missing application specific score function")
|
if p.SkipAtomicValidation {
|
||||||
|
p.AppSpecificScore = func(p peer.ID) float64 {
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
return fmt.Errorf("missing application specific score function")
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// check the IP colocation factor
|
if !p.SkipAtomicValidation || p.IPColocationFactorWeight != 0 {
|
||||||
if p.IPColocationFactorWeight > 0 || isInvalidNumber(p.IPColocationFactorWeight) {
|
// check the IP collocation factor
|
||||||
return fmt.Errorf("invalid IPColocationFactorWeight; must be negative (or 0 to disable) and a valid number")
|
if p.IPColocationFactorWeight > 0 || isInvalidNumber(p.IPColocationFactorWeight) {
|
||||||
}
|
return fmt.Errorf("invalid IPColocationFactorWeight; must be negative (or 0 to disable) and a valid number")
|
||||||
if p.IPColocationFactorWeight != 0 && p.IPColocationFactorThreshold < 1 {
|
}
|
||||||
return fmt.Errorf("invalid IPColocationFactorThreshold; must be at least 1")
|
if p.IPColocationFactorWeight != 0 && p.IPColocationFactorThreshold < 1 {
|
||||||
|
return fmt.Errorf("invalid IPColocationFactorThreshold; must be at least 1")
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// check the behaviour penalty
|
// check the behaviour penalty
|
||||||
if p.BehaviourPenaltyWeight > 0 || isInvalidNumber(p.BehaviourPenaltyWeight) {
|
if !p.SkipAtomicValidation || p.BehaviourPenaltyWeight != 0 || p.BehaviourPenaltyThreshold != 0 {
|
||||||
return fmt.Errorf("invalid BehaviourPenaltyWeight; must be negative (or 0 to disable) and a valid number")
|
if p.BehaviourPenaltyWeight > 0 || isInvalidNumber(p.BehaviourPenaltyWeight) {
|
||||||
}
|
return fmt.Errorf("invalid BehaviourPenaltyWeight; must be negative (or 0 to disable) and a valid number")
|
||||||
if p.BehaviourPenaltyWeight != 0 && (p.BehaviourPenaltyDecay <= 0 || p.BehaviourPenaltyDecay >= 1 || isInvalidNumber(p.BehaviourPenaltyDecay)) {
|
}
|
||||||
return fmt.Errorf("invalid BehaviourPenaltyDecay; must be between 0 and 1")
|
if p.BehaviourPenaltyWeight != 0 && (p.BehaviourPenaltyDecay <= 0 || p.BehaviourPenaltyDecay >= 1 || isInvalidNumber(p.BehaviourPenaltyDecay)) {
|
||||||
}
|
return fmt.Errorf("invalid BehaviourPenaltyDecay; must be between 0 and 1")
|
||||||
if p.BehaviourPenaltyThreshold < 0 || isInvalidNumber(p.BehaviourPenaltyThreshold) {
|
}
|
||||||
return fmt.Errorf("invalid BehaviourPenaltyThreshold; must be >= 0 and a valid number")
|
if p.BehaviourPenaltyThreshold < 0 || isInvalidNumber(p.BehaviourPenaltyThreshold) {
|
||||||
|
return fmt.Errorf("invalid BehaviourPenaltyThreshold; must be >= 0 and a valid number")
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// check the decay parameters
|
// check the decay parameters
|
||||||
if p.DecayInterval < time.Second {
|
if !p.SkipAtomicValidation || p.DecayInterval != 0 || p.DecayToZero != 0 {
|
||||||
return fmt.Errorf("invalid DecayInterval; must be at least 1s")
|
if p.DecayInterval < time.Second {
|
||||||
}
|
return fmt.Errorf("invalid DecayInterval; must be at least 1s")
|
||||||
if p.DecayToZero <= 0 || p.DecayToZero >= 1 || isInvalidNumber(p.DecayToZero) {
|
}
|
||||||
return fmt.Errorf("invalid DecayToZero; must be between 0 and 1")
|
if p.DecayToZero <= 0 || p.DecayToZero >= 1 || isInvalidNumber(p.DecayToZero) {
|
||||||
|
return fmt.Errorf("invalid DecayToZero; must be between 0 and 1")
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// no need to check the score retention; a value of 0 means that we don't retain scores
|
// no need to check the score retention; a value of 0 means that we don't retain scores
|
||||||
@ -207,6 +240,43 @@ func (p *TopicScoreParams) validate() error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// check P1
|
// check P1
|
||||||
|
if err := p.validateTimeInMeshParams(); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
// check P2
|
||||||
|
if err := p.validateMessageDeliveryParams(); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
// check P3
|
||||||
|
if err := p.validateMeshMessageDeliveryParams(); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
// check P3b
|
||||||
|
if err := p.validateMessageFailurePenaltyParams(); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
// check P4
|
||||||
|
if err := p.validateInvalidMessageDeliveryParams(); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *TopicScoreParams) validateTimeInMeshParams() error {
|
||||||
|
if p.SkipAtomicValidation {
|
||||||
|
// in non-atomic mode, parameters at their zero values are dismissed from validation.
|
||||||
|
if p.TimeInMeshWeight == 0 && p.TimeInMeshQuantum == 0 && p.TimeInMeshCap == 0 {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// either atomic validation mode, or some parameters have been set a value,
|
||||||
|
// hence, proceed with normal validation of all related parameters in this context.
|
||||||
|
|
||||||
if p.TimeInMeshQuantum == 0 {
|
if p.TimeInMeshQuantum == 0 {
|
||||||
return fmt.Errorf("invalid TimeInMeshQuantum; must be non zero")
|
return fmt.Errorf("invalid TimeInMeshQuantum; must be non zero")
|
||||||
}
|
}
|
||||||
@ -220,7 +290,20 @@ func (p *TopicScoreParams) validate() error {
|
|||||||
return fmt.Errorf("invalid TimeInMeshCap; must be positive and a valid number")
|
return fmt.Errorf("invalid TimeInMeshCap; must be positive and a valid number")
|
||||||
}
|
}
|
||||||
|
|
||||||
// check P2
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *TopicScoreParams) validateMessageDeliveryParams() error {
|
||||||
|
if p.SkipAtomicValidation {
|
||||||
|
// in non-atomic mode, parameters at their zero values are dismissed from validation.
|
||||||
|
if p.FirstMessageDeliveriesWeight == 0 && p.FirstMessageDeliveriesCap == 0 && p.FirstMessageDeliveriesDecay == 0 {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// either atomic validation mode, or some parameters have been set a value,
|
||||||
|
// hence, proceed with normal validation of all related parameters in this context.
|
||||||
|
|
||||||
if p.FirstMessageDeliveriesWeight < 0 || isInvalidNumber(p.FirstMessageDeliveriesWeight) {
|
if p.FirstMessageDeliveriesWeight < 0 || isInvalidNumber(p.FirstMessageDeliveriesWeight) {
|
||||||
return fmt.Errorf("invallid FirstMessageDeliveriesWeight; must be positive (or 0 to disable) and a valid number")
|
return fmt.Errorf("invallid FirstMessageDeliveriesWeight; must be positive (or 0 to disable) and a valid number")
|
||||||
}
|
}
|
||||||
@ -231,7 +314,25 @@ func (p *TopicScoreParams) validate() error {
|
|||||||
return fmt.Errorf("invalid FirstMessageDeliveriesCap; must be positive and a valid number")
|
return fmt.Errorf("invalid FirstMessageDeliveriesCap; must be positive and a valid number")
|
||||||
}
|
}
|
||||||
|
|
||||||
// check P3
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *TopicScoreParams) validateMeshMessageDeliveryParams() error {
|
||||||
|
if p.SkipAtomicValidation {
|
||||||
|
// in non-atomic mode, parameters at their zero values are dismissed from validation.
|
||||||
|
if p.MeshMessageDeliveriesWeight == 0 &&
|
||||||
|
p.MeshMessageDeliveriesCap == 0 &&
|
||||||
|
p.MeshMessageDeliveriesDecay == 0 &&
|
||||||
|
p.MeshMessageDeliveriesThreshold == 0 &&
|
||||||
|
p.MeshMessageDeliveriesWindow == 0 &&
|
||||||
|
p.MeshMessageDeliveriesActivation == 0 {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// either atomic validation mode, or some parameters have been set a value,
|
||||||
|
// hence, proceed with normal validation of all related parameters in this context.
|
||||||
|
|
||||||
if p.MeshMessageDeliveriesWeight > 0 || isInvalidNumber(p.MeshMessageDeliveriesWeight) {
|
if p.MeshMessageDeliveriesWeight > 0 || isInvalidNumber(p.MeshMessageDeliveriesWeight) {
|
||||||
return fmt.Errorf("invalid MeshMessageDeliveriesWeight; must be negative (or 0 to disable) and a valid number")
|
return fmt.Errorf("invalid MeshMessageDeliveriesWeight; must be negative (or 0 to disable) and a valid number")
|
||||||
}
|
}
|
||||||
@ -251,7 +352,20 @@ func (p *TopicScoreParams) validate() error {
|
|||||||
return fmt.Errorf("invalid MeshMessageDeliveriesActivation; must be at least 1s")
|
return fmt.Errorf("invalid MeshMessageDeliveriesActivation; must be at least 1s")
|
||||||
}
|
}
|
||||||
|
|
||||||
// check P3b
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *TopicScoreParams) validateMessageFailurePenaltyParams() error {
|
||||||
|
if p.SkipAtomicValidation {
|
||||||
|
// in selective mode, parameters at their zero values are dismissed from validation.
|
||||||
|
if p.MeshFailurePenaltyDecay == 0 && p.MeshFailurePenaltyWeight == 0 {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// either atomic validation mode, or some parameters have been set a value,
|
||||||
|
// hence, proceed with normal validation of all related parameters in this context.
|
||||||
|
|
||||||
if p.MeshFailurePenaltyWeight > 0 || isInvalidNumber(p.MeshFailurePenaltyWeight) {
|
if p.MeshFailurePenaltyWeight > 0 || isInvalidNumber(p.MeshFailurePenaltyWeight) {
|
||||||
return fmt.Errorf("invalid MeshFailurePenaltyWeight; must be negative (or 0 to disable) and a valid number")
|
return fmt.Errorf("invalid MeshFailurePenaltyWeight; must be negative (or 0 to disable) and a valid number")
|
||||||
}
|
}
|
||||||
@ -259,7 +373,20 @@ func (p *TopicScoreParams) validate() error {
|
|||||||
return fmt.Errorf("invalid MeshFailurePenaltyDecay; must be between 0 and 1")
|
return fmt.Errorf("invalid MeshFailurePenaltyDecay; must be between 0 and 1")
|
||||||
}
|
}
|
||||||
|
|
||||||
// check P4
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *TopicScoreParams) validateInvalidMessageDeliveryParams() error {
|
||||||
|
if p.SkipAtomicValidation {
|
||||||
|
// in selective mode, parameters at their zero values are dismissed from validation.
|
||||||
|
if p.InvalidMessageDeliveriesDecay == 0 && p.InvalidMessageDeliveriesWeight == 0 {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// either atomic validation mode, or some parameters have been set a value,
|
||||||
|
// hence, proceed with normal validation of all related parameters in this context.
|
||||||
|
|
||||||
if p.InvalidMessageDeliveriesWeight > 0 || isInvalidNumber(p.InvalidMessageDeliveriesWeight) {
|
if p.InvalidMessageDeliveriesWeight > 0 || isInvalidNumber(p.InvalidMessageDeliveriesWeight) {
|
||||||
return fmt.Errorf("invalid InvalidMessageDeliveriesWeight; must be negative (or 0 to disable) and a valid number")
|
return fmt.Errorf("invalid InvalidMessageDeliveriesWeight; must be negative (or 0 to disable) and a valid number")
|
||||||
}
|
}
|
||||||
@ -281,7 +408,7 @@ func ScoreParameterDecay(decay time.Duration) float64 {
|
|||||||
return ScoreParameterDecayWithBase(decay, DefaultDecayInterval, DefaultDecayToZero)
|
return ScoreParameterDecayWithBase(decay, DefaultDecayInterval, DefaultDecayToZero)
|
||||||
}
|
}
|
||||||
|
|
||||||
// ScoreParameterDecay computes the decay factor for a parameter using base as the DecayInterval
|
// ScoreParameterDecayWithBase computes the decay factor for a parameter using base as the DecayInterval
|
||||||
func ScoreParameterDecayWithBase(decay time.Duration, base time.Duration, decayToZero float64) float64 {
|
func ScoreParameterDecayWithBase(decay time.Duration, base time.Duration, decayToZero float64) float64 {
|
||||||
// the decay is linear, so after n ticks the value is factor^n
|
// the decay is linear, so after n ticks the value is factor^n
|
||||||
// so factor^n = decayToZero => factor = decayToZero^(1/n)
|
// so factor^n = decayToZero => factor = decayToZero^(1/n)
|
||||||
|
|||||||
@ -8,121 +8,317 @@ import (
|
|||||||
"github.com/libp2p/go-libp2p/core/peer"
|
"github.com/libp2p/go-libp2p/core/peer"
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestPeerScoreThresholdsValidation(t *testing.T) {
|
func TestPeerScoreThreshold_AtomicValidation(t *testing.T) {
|
||||||
if (&PeerScoreThresholds{GossipThreshold: 1}).validate() == nil {
|
testPeerScoreThresholdsValidation(t, false)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestPeerScoreThreshold_SkipAtomicValidation(t *testing.T) {
|
||||||
|
testPeerScoreThresholdsValidation(t, true)
|
||||||
|
}
|
||||||
|
|
||||||
|
func testPeerScoreThresholdsValidation(t *testing.T, skipAtomicValidation bool) {
|
||||||
|
if (&PeerScoreThresholds{
|
||||||
|
SkipAtomicValidation: skipAtomicValidation,
|
||||||
|
GossipThreshold: 1,
|
||||||
|
}).validate() == nil {
|
||||||
t.Fatal("expected validation error")
|
t.Fatal("expected validation error")
|
||||||
}
|
}
|
||||||
if (&PeerScoreThresholds{PublishThreshold: 1}).validate() == nil {
|
if (&PeerScoreThresholds{
|
||||||
|
SkipAtomicValidation: skipAtomicValidation,
|
||||||
|
PublishThreshold: 1,
|
||||||
|
}).validate() == nil {
|
||||||
t.Fatal("expected validation error")
|
t.Fatal("expected validation error")
|
||||||
}
|
}
|
||||||
if (&PeerScoreThresholds{GossipThreshold: -1, PublishThreshold: 0}).validate() == nil {
|
|
||||||
|
if (&PeerScoreThresholds{
|
||||||
|
SkipAtomicValidation: skipAtomicValidation,
|
||||||
|
GossipThreshold: -1,
|
||||||
|
PublishThreshold: 0,
|
||||||
|
}).validate() == nil {
|
||||||
t.Fatal("expected validation error")
|
t.Fatal("expected validation error")
|
||||||
}
|
}
|
||||||
if (&PeerScoreThresholds{GossipThreshold: -1, PublishThreshold: -2, GraylistThreshold: 0}).validate() == nil {
|
if (&PeerScoreThresholds{
|
||||||
|
SkipAtomicValidation: skipAtomicValidation,
|
||||||
|
GossipThreshold: -1,
|
||||||
|
PublishThreshold: -2,
|
||||||
|
GraylistThreshold: 0,
|
||||||
|
}).validate() == nil {
|
||||||
t.Fatal("expected validation error")
|
t.Fatal("expected validation error")
|
||||||
}
|
}
|
||||||
if (&PeerScoreThresholds{AcceptPXThreshold: -1}).validate() == nil {
|
if (&PeerScoreThresholds{
|
||||||
|
SkipAtomicValidation: skipAtomicValidation,
|
||||||
|
AcceptPXThreshold: -1,
|
||||||
|
}).validate() == nil {
|
||||||
t.Fatal("expected validation error")
|
t.Fatal("expected validation error")
|
||||||
}
|
}
|
||||||
if (&PeerScoreThresholds{OpportunisticGraftThreshold: -1}).validate() == nil {
|
if (&PeerScoreThresholds{
|
||||||
|
SkipAtomicValidation: skipAtomicValidation,
|
||||||
|
OpportunisticGraftThreshold: -1,
|
||||||
|
}).validate() == nil {
|
||||||
t.Fatal("expected validation error")
|
t.Fatal("expected validation error")
|
||||||
}
|
}
|
||||||
if (&PeerScoreThresholds{GossipThreshold: -1, PublishThreshold: -2, GraylistThreshold: -3, AcceptPXThreshold: 1, OpportunisticGraftThreshold: 2}).validate() != nil {
|
if (&PeerScoreThresholds{
|
||||||
|
SkipAtomicValidation: skipAtomicValidation,
|
||||||
|
GossipThreshold: -1,
|
||||||
|
PublishThreshold: -2,
|
||||||
|
GraylistThreshold: -3,
|
||||||
|
AcceptPXThreshold: 1,
|
||||||
|
OpportunisticGraftThreshold: 2}).validate() != nil {
|
||||||
t.Fatal("expected validation success")
|
t.Fatal("expected validation success")
|
||||||
}
|
}
|
||||||
if (&PeerScoreThresholds{GossipThreshold: math.Inf(-1), PublishThreshold: -2, GraylistThreshold: -3, AcceptPXThreshold: 1, OpportunisticGraftThreshold: 2}).validate() == nil {
|
if (&PeerScoreThresholds{
|
||||||
|
SkipAtomicValidation: skipAtomicValidation,
|
||||||
|
GossipThreshold: math.Inf(-1),
|
||||||
|
PublishThreshold: -2,
|
||||||
|
GraylistThreshold: -3,
|
||||||
|
AcceptPXThreshold: 1,
|
||||||
|
OpportunisticGraftThreshold: 2,
|
||||||
|
}).validate() == nil {
|
||||||
t.Fatal("expected validation error")
|
t.Fatal("expected validation error")
|
||||||
}
|
}
|
||||||
if (&PeerScoreThresholds{GossipThreshold: -1, PublishThreshold: math.Inf(-1), GraylistThreshold: -3, AcceptPXThreshold: 1, OpportunisticGraftThreshold: 2}).validate() == nil {
|
if (&PeerScoreThresholds{
|
||||||
|
SkipAtomicValidation: skipAtomicValidation,
|
||||||
|
GossipThreshold: -1,
|
||||||
|
PublishThreshold: math.Inf(-1),
|
||||||
|
GraylistThreshold: -3,
|
||||||
|
AcceptPXThreshold: 1,
|
||||||
|
OpportunisticGraftThreshold: 2,
|
||||||
|
}).validate() == nil {
|
||||||
t.Fatal("expected validation error")
|
t.Fatal("expected validation error")
|
||||||
}
|
}
|
||||||
if (&PeerScoreThresholds{GossipThreshold: -1, PublishThreshold: -2, GraylistThreshold: math.Inf(-1), AcceptPXThreshold: 1, OpportunisticGraftThreshold: 2}).validate() == nil {
|
if (&PeerScoreThresholds{
|
||||||
|
SkipAtomicValidation: skipAtomicValidation,
|
||||||
|
GossipThreshold: -1,
|
||||||
|
PublishThreshold: -2,
|
||||||
|
GraylistThreshold: math.Inf(-1),
|
||||||
|
AcceptPXThreshold: 1,
|
||||||
|
OpportunisticGraftThreshold: 2,
|
||||||
|
}).validate() == nil {
|
||||||
t.Fatal("expected validation error")
|
t.Fatal("expected validation error")
|
||||||
}
|
}
|
||||||
if (&PeerScoreThresholds{GossipThreshold: -1, PublishThreshold: -2, GraylistThreshold: -3, AcceptPXThreshold: math.NaN(), OpportunisticGraftThreshold: 2}).validate() == nil {
|
if (&PeerScoreThresholds{
|
||||||
|
SkipAtomicValidation: skipAtomicValidation,
|
||||||
|
GossipThreshold: -1,
|
||||||
|
PublishThreshold: -2,
|
||||||
|
GraylistThreshold: -3,
|
||||||
|
AcceptPXThreshold: math.NaN(),
|
||||||
|
OpportunisticGraftThreshold: 2,
|
||||||
|
}).validate() == nil {
|
||||||
t.Fatal("expected validation error")
|
t.Fatal("expected validation error")
|
||||||
}
|
}
|
||||||
if (&PeerScoreThresholds{GossipThreshold: -1, PublishThreshold: -2, GraylistThreshold: -3, AcceptPXThreshold: 1, OpportunisticGraftThreshold: math.Inf(0)}).validate() == nil {
|
if (&PeerScoreThresholds{
|
||||||
|
SkipAtomicValidation: skipAtomicValidation,
|
||||||
|
GossipThreshold: -1,
|
||||||
|
PublishThreshold: -2,
|
||||||
|
GraylistThreshold: -3,
|
||||||
|
AcceptPXThreshold: 1,
|
||||||
|
OpportunisticGraftThreshold: math.Inf(0),
|
||||||
|
}).validate() == nil {
|
||||||
t.Fatal("expected validation error")
|
t.Fatal("expected validation error")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestTopicScoreParamsValidation(t *testing.T) {
|
func TestTopicScoreParamsValidation_InvalidParams_AtomicValidation(t *testing.T) {
|
||||||
if (&TopicScoreParams{}).validate() == nil {
|
testTopicScoreParamsValidationWithInvalidParameters(t, false)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestTopicScoreParamsValidation_InvalidParams_SkipAtomicValidation(t *testing.T) {
|
||||||
|
testTopicScoreParamsValidationWithInvalidParameters(t, true)
|
||||||
|
}
|
||||||
|
|
||||||
|
func testTopicScoreParamsValidationWithInvalidParameters(t *testing.T, skipAtomicValidation bool) {
|
||||||
|
|
||||||
|
if skipAtomicValidation {
|
||||||
|
if (&TopicScoreParams{
|
||||||
|
SkipAtomicValidation: true}).validate() != nil {
|
||||||
|
t.Fatal("expected validation success")
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (&TopicScoreParams{}).validate() == nil {
|
||||||
|
t.Fatal("expected validation failure")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (&TopicScoreParams{
|
||||||
|
SkipAtomicValidation: skipAtomicValidation,
|
||||||
|
TopicWeight: -1,
|
||||||
|
}).validate() == nil {
|
||||||
t.Fatal("expected validation error")
|
t.Fatal("expected validation error")
|
||||||
}
|
}
|
||||||
|
|
||||||
if (&TopicScoreParams{TopicWeight: -1}).validate() == nil {
|
if (&TopicScoreParams{
|
||||||
|
SkipAtomicValidation: skipAtomicValidation,
|
||||||
|
TimeInMeshWeight: -1,
|
||||||
|
TimeInMeshQuantum: time.Second,
|
||||||
|
}).validate() == nil {
|
||||||
|
t.Fatal("expected validation error")
|
||||||
|
}
|
||||||
|
if (&TopicScoreParams{
|
||||||
|
SkipAtomicValidation: skipAtomicValidation,
|
||||||
|
TimeInMeshWeight: 1,
|
||||||
|
TimeInMeshQuantum: -1,
|
||||||
|
}).validate() == nil {
|
||||||
|
t.Fatal("expected validation error")
|
||||||
|
}
|
||||||
|
if (&TopicScoreParams{
|
||||||
|
SkipAtomicValidation: skipAtomicValidation,
|
||||||
|
TimeInMeshWeight: 1,
|
||||||
|
TimeInMeshQuantum: time.Second,
|
||||||
|
TimeInMeshCap: -1,
|
||||||
|
}).validate() == nil {
|
||||||
t.Fatal("expected validation error")
|
t.Fatal("expected validation error")
|
||||||
}
|
}
|
||||||
|
|
||||||
if (&TopicScoreParams{TimeInMeshWeight: -1, TimeInMeshQuantum: time.Second}).validate() == nil {
|
if (&TopicScoreParams{
|
||||||
|
SkipAtomicValidation: skipAtomicValidation,
|
||||||
|
TimeInMeshQuantum: time.Second,
|
||||||
|
FirstMessageDeliveriesWeight: -1,
|
||||||
|
}).validate() == nil {
|
||||||
t.Fatal("expected validation error")
|
t.Fatal("expected validation error")
|
||||||
}
|
}
|
||||||
if (&TopicScoreParams{TimeInMeshWeight: 1, TimeInMeshQuantum: -1}).validate() == nil {
|
if (&TopicScoreParams{
|
||||||
|
SkipAtomicValidation: skipAtomicValidation,
|
||||||
|
TimeInMeshQuantum: time.Second,
|
||||||
|
FirstMessageDeliveriesWeight: 1,
|
||||||
|
FirstMessageDeliveriesDecay: -1,
|
||||||
|
}).validate() == nil {
|
||||||
t.Fatal("expected validation error")
|
t.Fatal("expected validation error")
|
||||||
}
|
}
|
||||||
if (&TopicScoreParams{TimeInMeshWeight: 1, TimeInMeshQuantum: time.Second, TimeInMeshCap: -1}).validate() == nil {
|
if (&TopicScoreParams{
|
||||||
|
SkipAtomicValidation: skipAtomicValidation,
|
||||||
|
TimeInMeshQuantum: time.Second,
|
||||||
|
FirstMessageDeliveriesWeight: 1,
|
||||||
|
FirstMessageDeliveriesDecay: 2,
|
||||||
|
}).validate() == nil {
|
||||||
|
t.Fatal("expected validation error")
|
||||||
|
}
|
||||||
|
if (&TopicScoreParams{
|
||||||
|
SkipAtomicValidation: skipAtomicValidation,
|
||||||
|
TimeInMeshQuantum: time.Second,
|
||||||
|
FirstMessageDeliveriesWeight: 1,
|
||||||
|
FirstMessageDeliveriesDecay: .5,
|
||||||
|
FirstMessageDeliveriesCap: -1,
|
||||||
|
}).validate() == nil {
|
||||||
t.Fatal("expected validation error")
|
t.Fatal("expected validation error")
|
||||||
}
|
}
|
||||||
|
|
||||||
if (&TopicScoreParams{TimeInMeshQuantum: time.Second, FirstMessageDeliveriesWeight: -1}).validate() == nil {
|
if (&TopicScoreParams{
|
||||||
|
SkipAtomicValidation: skipAtomicValidation,
|
||||||
|
TimeInMeshQuantum: time.Second,
|
||||||
|
MeshMessageDeliveriesWeight: 1,
|
||||||
|
}).validate() == nil {
|
||||||
t.Fatal("expected validation error")
|
t.Fatal("expected validation error")
|
||||||
}
|
}
|
||||||
if (&TopicScoreParams{TimeInMeshQuantum: time.Second, FirstMessageDeliveriesWeight: 1, FirstMessageDeliveriesDecay: -1}).validate() == nil {
|
if (&TopicScoreParams{
|
||||||
|
SkipAtomicValidation: skipAtomicValidation,
|
||||||
|
TimeInMeshQuantum: time.Second,
|
||||||
|
MeshMessageDeliveriesWeight: -1,
|
||||||
|
MeshMessageDeliveriesDecay: -1,
|
||||||
|
}).validate() == nil {
|
||||||
t.Fatal("expected validation error")
|
t.Fatal("expected validation error")
|
||||||
}
|
}
|
||||||
if (&TopicScoreParams{TimeInMeshQuantum: time.Second, FirstMessageDeliveriesWeight: 1, FirstMessageDeliveriesDecay: 2}).validate() == nil {
|
if (&TopicScoreParams{
|
||||||
|
SkipAtomicValidation: skipAtomicValidation,
|
||||||
|
TimeInMeshQuantum: time.Second,
|
||||||
|
MeshMessageDeliveriesWeight: -1,
|
||||||
|
MeshMessageDeliveriesDecay: 2}).validate() == nil {
|
||||||
t.Fatal("expected validation error")
|
t.Fatal("expected validation error")
|
||||||
}
|
}
|
||||||
if (&TopicScoreParams{TimeInMeshQuantum: time.Second, FirstMessageDeliveriesWeight: 1, FirstMessageDeliveriesDecay: .5, FirstMessageDeliveriesCap: -1}).validate() == nil {
|
if (&TopicScoreParams{
|
||||||
|
SkipAtomicValidation: skipAtomicValidation,
|
||||||
|
TimeInMeshQuantum: time.Second,
|
||||||
|
MeshMessageDeliveriesWeight: -1,
|
||||||
|
MeshMessageDeliveriesDecay: .5,
|
||||||
|
MeshMessageDeliveriesCap: -1,
|
||||||
|
}).validate() == nil {
|
||||||
|
t.Fatal("expected validation error")
|
||||||
|
}
|
||||||
|
if (&TopicScoreParams{
|
||||||
|
SkipAtomicValidation: skipAtomicValidation,
|
||||||
|
TimeInMeshQuantum: time.Second,
|
||||||
|
MeshMessageDeliveriesWeight: -1,
|
||||||
|
MeshMessageDeliveriesDecay: .5,
|
||||||
|
MeshMessageDeliveriesCap: 5,
|
||||||
|
MeshMessageDeliveriesThreshold: -3,
|
||||||
|
}).validate() == nil {
|
||||||
|
t.Fatal("expected validation error")
|
||||||
|
}
|
||||||
|
if (&TopicScoreParams{
|
||||||
|
SkipAtomicValidation: skipAtomicValidation,
|
||||||
|
TimeInMeshQuantum: time.Second,
|
||||||
|
MeshMessageDeliveriesWeight: -1,
|
||||||
|
MeshMessageDeliveriesDecay: .5,
|
||||||
|
MeshMessageDeliveriesCap: 5,
|
||||||
|
MeshMessageDeliveriesThreshold: 3,
|
||||||
|
MeshMessageDeliveriesWindow: -1,
|
||||||
|
}).validate() == nil {
|
||||||
|
t.Fatal("expected validation error")
|
||||||
|
}
|
||||||
|
if (&TopicScoreParams{
|
||||||
|
SkipAtomicValidation: skipAtomicValidation,
|
||||||
|
TimeInMeshQuantum: time.Second,
|
||||||
|
MeshMessageDeliveriesWeight: -1,
|
||||||
|
MeshMessageDeliveriesDecay: .5,
|
||||||
|
MeshMessageDeliveriesCap: 5,
|
||||||
|
MeshMessageDeliveriesThreshold: 3,
|
||||||
|
MeshMessageDeliveriesWindow: time.Millisecond,
|
||||||
|
MeshMessageDeliveriesActivation: time.Millisecond}).validate() == nil {
|
||||||
t.Fatal("expected validation error")
|
t.Fatal("expected validation error")
|
||||||
}
|
}
|
||||||
|
|
||||||
if (&TopicScoreParams{TimeInMeshQuantum: time.Second, MeshMessageDeliveriesWeight: 1}).validate() == nil {
|
if (&TopicScoreParams{
|
||||||
|
SkipAtomicValidation: skipAtomicValidation,
|
||||||
|
TimeInMeshQuantum: time.Second,
|
||||||
|
MeshFailurePenaltyWeight: 1,
|
||||||
|
}).validate() == nil {
|
||||||
t.Fatal("expected validation error")
|
t.Fatal("expected validation error")
|
||||||
}
|
}
|
||||||
if (&TopicScoreParams{TimeInMeshQuantum: time.Second, MeshMessageDeliveriesWeight: -1, MeshMessageDeliveriesDecay: -1}).validate() == nil {
|
if (&TopicScoreParams{
|
||||||
|
SkipAtomicValidation: skipAtomicValidation,
|
||||||
|
TimeInMeshQuantum: time.Second,
|
||||||
|
MeshFailurePenaltyWeight: -1,
|
||||||
|
MeshFailurePenaltyDecay: -1,
|
||||||
|
}).validate() == nil {
|
||||||
t.Fatal("expected validation error")
|
t.Fatal("expected validation error")
|
||||||
}
|
}
|
||||||
if (&TopicScoreParams{TimeInMeshQuantum: time.Second, MeshMessageDeliveriesWeight: -1, MeshMessageDeliveriesDecay: 2}).validate() == nil {
|
if (&TopicScoreParams{
|
||||||
t.Fatal("expected validation error")
|
SkipAtomicValidation: skipAtomicValidation,
|
||||||
}
|
TimeInMeshQuantum: time.Second,
|
||||||
if (&TopicScoreParams{TimeInMeshQuantum: time.Second, MeshMessageDeliveriesWeight: -1, MeshMessageDeliveriesDecay: .5, MeshMessageDeliveriesCap: -1}).validate() == nil {
|
MeshFailurePenaltyWeight: -1,
|
||||||
t.Fatal("expected validation error")
|
MeshFailurePenaltyDecay: 2,
|
||||||
}
|
}).validate() == nil {
|
||||||
if (&TopicScoreParams{TimeInMeshQuantum: time.Second, MeshMessageDeliveriesWeight: -1, MeshMessageDeliveriesDecay: .5, MeshMessageDeliveriesCap: 5, MeshMessageDeliveriesThreshold: -3}).validate() == nil {
|
|
||||||
t.Fatal("expected validation error")
|
|
||||||
}
|
|
||||||
if (&TopicScoreParams{TimeInMeshQuantum: time.Second, MeshMessageDeliveriesWeight: -1, MeshMessageDeliveriesDecay: .5, MeshMessageDeliveriesCap: 5, MeshMessageDeliveriesThreshold: 3, MeshMessageDeliveriesWindow: -1}).validate() == nil {
|
|
||||||
t.Fatal("expected validation error")
|
|
||||||
}
|
|
||||||
if (&TopicScoreParams{TimeInMeshQuantum: time.Second, MeshMessageDeliveriesWeight: -1, MeshMessageDeliveriesDecay: .5, MeshMessageDeliveriesCap: 5, MeshMessageDeliveriesThreshold: 3, MeshMessageDeliveriesWindow: time.Millisecond, MeshMessageDeliveriesActivation: time.Millisecond}).validate() == nil {
|
|
||||||
t.Fatal("expected validation error")
|
t.Fatal("expected validation error")
|
||||||
}
|
}
|
||||||
|
|
||||||
if (&TopicScoreParams{TimeInMeshQuantum: time.Second, MeshFailurePenaltyWeight: 1}).validate() == nil {
|
if (&TopicScoreParams{
|
||||||
|
SkipAtomicValidation: skipAtomicValidation,
|
||||||
|
TimeInMeshQuantum: time.Second,
|
||||||
|
InvalidMessageDeliveriesWeight: 1,
|
||||||
|
}).validate() == nil {
|
||||||
t.Fatal("expected validation error")
|
t.Fatal("expected validation error")
|
||||||
}
|
}
|
||||||
if (&TopicScoreParams{TimeInMeshQuantum: time.Second, MeshFailurePenaltyWeight: -1, MeshFailurePenaltyDecay: -1}).validate() == nil {
|
if (&TopicScoreParams{
|
||||||
|
SkipAtomicValidation: skipAtomicValidation,
|
||||||
|
TimeInMeshQuantum: time.Second,
|
||||||
|
InvalidMessageDeliveriesWeight: -1,
|
||||||
|
InvalidMessageDeliveriesDecay: -1,
|
||||||
|
}).validate() == nil {
|
||||||
t.Fatal("expected validation error")
|
t.Fatal("expected validation error")
|
||||||
}
|
}
|
||||||
if (&TopicScoreParams{TimeInMeshQuantum: time.Second, MeshFailurePenaltyWeight: -1, MeshFailurePenaltyDecay: 2}).validate() == nil {
|
if (&TopicScoreParams{
|
||||||
t.Fatal("expected validation error")
|
SkipAtomicValidation: skipAtomicValidation,
|
||||||
}
|
TimeInMeshQuantum: time.Second,
|
||||||
|
InvalidMessageDeliveriesWeight: -1,
|
||||||
if (&TopicScoreParams{TimeInMeshQuantum: time.Second, InvalidMessageDeliveriesWeight: 1}).validate() == nil {
|
InvalidMessageDeliveriesDecay: 2,
|
||||||
t.Fatal("expected validation error")
|
}).validate() == nil {
|
||||||
}
|
|
||||||
if (&TopicScoreParams{TimeInMeshQuantum: time.Second, InvalidMessageDeliveriesWeight: -1, InvalidMessageDeliveriesDecay: -1}).validate() == nil {
|
|
||||||
t.Fatal("expected validation error")
|
|
||||||
}
|
|
||||||
if (&TopicScoreParams{TimeInMeshQuantum: time.Second, InvalidMessageDeliveriesWeight: -1, InvalidMessageDeliveriesDecay: 2}).validate() == nil {
|
|
||||||
t.Fatal("expected validation error")
|
t.Fatal("expected validation error")
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestTopicScoreParamsValidation_ValidParams_AtomicValidation(t *testing.T) {
|
||||||
// Don't use these params in production!
|
// Don't use these params in production!
|
||||||
if (&TopicScoreParams{
|
if (&TopicScoreParams{
|
||||||
|
SkipAtomicValidation: false,
|
||||||
TopicWeight: 1,
|
TopicWeight: 1,
|
||||||
TimeInMeshWeight: 0.01,
|
TimeInMeshWeight: 0.01,
|
||||||
TimeInMeshQuantum: time.Second,
|
TimeInMeshQuantum: time.Second,
|
||||||
@ -145,148 +341,177 @@ func TestTopicScoreParamsValidation(t *testing.T) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestPeerScoreParamsValidation(t *testing.T) {
|
func TestTopicScoreParamsValidation_NonAtomicValidation(t *testing.T) {
|
||||||
|
// Don't use these params in production!
|
||||||
|
// In non-atomic (selective) validation mode, the subset of parameters passes
|
||||||
|
// validation if the individual parameters values pass validation.
|
||||||
|
p := &TopicScoreParams{}
|
||||||
|
setTopicParamAndValidate(t, p, func(params *TopicScoreParams) {
|
||||||
|
params.SkipAtomicValidation = true
|
||||||
|
})
|
||||||
|
// including topic weight.
|
||||||
|
setTopicParamAndValidate(t, p, func(params *TopicScoreParams) {
|
||||||
|
params.TopicWeight = 1
|
||||||
|
})
|
||||||
|
// including time in mesh parameters.
|
||||||
|
setTopicParamAndValidate(t, p, func(params *TopicScoreParams) {
|
||||||
|
params.TimeInMeshWeight = 0.01
|
||||||
|
params.TimeInMeshQuantum = time.Second
|
||||||
|
params.TimeInMeshCap = 10
|
||||||
|
})
|
||||||
|
// including first message delivery parameters.
|
||||||
|
setTopicParamAndValidate(t, p, func(params *TopicScoreParams) {
|
||||||
|
params.FirstMessageDeliveriesWeight = 1
|
||||||
|
params.FirstMessageDeliveriesDecay = 0.5
|
||||||
|
params.FirstMessageDeliveriesCap = 10
|
||||||
|
})
|
||||||
|
// including mesh message delivery parameters.
|
||||||
|
setTopicParamAndValidate(t, p, func(params *TopicScoreParams) {
|
||||||
|
params.MeshMessageDeliveriesWeight = -1
|
||||||
|
params.MeshMessageDeliveriesDecay = 0.5
|
||||||
|
params.MeshMessageDeliveriesCap = 10
|
||||||
|
params.MeshMessageDeliveriesThreshold = 5
|
||||||
|
params.MeshMessageDeliveriesWindow = time.Millisecond
|
||||||
|
params.MeshMessageDeliveriesActivation = time.Second
|
||||||
|
})
|
||||||
|
// including mesh failure penalty parameters.
|
||||||
|
setTopicParamAndValidate(t, p, func(params *TopicScoreParams) {
|
||||||
|
params.MeshFailurePenaltyWeight = -1
|
||||||
|
params.MeshFailurePenaltyDecay = 0.5
|
||||||
|
})
|
||||||
|
// including invalid message delivery parameters.
|
||||||
|
setTopicParamAndValidate(t, p, func(params *TopicScoreParams) {
|
||||||
|
params.InvalidMessageDeliveriesWeight = -1
|
||||||
|
params.InvalidMessageDeliveriesDecay = 0.5
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestPeerScoreParamsValidation_InvalidParams_AtomicValidation(t *testing.T) {
|
||||||
|
testPeerScoreParamsValidationWithInvalidParams(t, false)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestPeerScoreParamsValidation_InvalidParams_SkipAtomicValidation(t *testing.T) {
|
||||||
|
testPeerScoreParamsValidationWithInvalidParams(t, true)
|
||||||
|
}
|
||||||
|
|
||||||
|
func testPeerScoreParamsValidationWithInvalidParams(t *testing.T, skipAtomicValidation bool) {
|
||||||
appScore := func(peer.ID) float64 { return 0 }
|
appScore := func(peer.ID) float64 { return 0 }
|
||||||
|
|
||||||
if (&PeerScoreParams{TopicScoreCap: -1, AppSpecificScore: appScore, DecayInterval: time.Second, DecayToZero: 0.01}).validate() == nil {
|
|
||||||
t.Fatal("expected validation error")
|
|
||||||
}
|
|
||||||
if (&PeerScoreParams{TopicScoreCap: 1, DecayInterval: time.Second, DecayToZero: 0.01}).validate() == nil {
|
|
||||||
t.Fatal("expected validation error")
|
|
||||||
}
|
|
||||||
if (&PeerScoreParams{TopicScoreCap: 1, AppSpecificScore: appScore, DecayInterval: time.Second, DecayToZero: 0.01, IPColocationFactorWeight: 1}).validate() == nil {
|
|
||||||
t.Fatal("expected validation error")
|
|
||||||
}
|
|
||||||
if (&PeerScoreParams{TopicScoreCap: 1, AppSpecificScore: appScore, DecayInterval: time.Second, DecayToZero: 0.01, IPColocationFactorWeight: -1, IPColocationFactorThreshold: -1}).validate() == nil {
|
|
||||||
t.Fatal("expected validation error")
|
|
||||||
}
|
|
||||||
if (&PeerScoreParams{TopicScoreCap: 1, AppSpecificScore: appScore, DecayInterval: time.Millisecond, DecayToZero: 0.01, IPColocationFactorWeight: -1, IPColocationFactorThreshold: 1}).validate() == nil {
|
|
||||||
t.Fatal("expected validation error")
|
|
||||||
}
|
|
||||||
if (&PeerScoreParams{TopicScoreCap: 1, AppSpecificScore: appScore, DecayInterval: time.Second, DecayToZero: -1, IPColocationFactorWeight: -1, IPColocationFactorThreshold: 1}).validate() == nil {
|
|
||||||
t.Fatal("expected validation error")
|
|
||||||
}
|
|
||||||
if (&PeerScoreParams{TopicScoreCap: 1, AppSpecificScore: appScore, DecayInterval: time.Second, DecayToZero: 2, IPColocationFactorWeight: -1, IPColocationFactorThreshold: 1}).validate() == nil {
|
|
||||||
t.Fatal("expected validation error")
|
|
||||||
}
|
|
||||||
if (&PeerScoreParams{AppSpecificScore: appScore, DecayInterval: time.Second, DecayToZero: 0.01, BehaviourPenaltyWeight: 1}).validate() == nil {
|
|
||||||
t.Fatal("expected validation error")
|
|
||||||
}
|
|
||||||
if (&PeerScoreParams{AppSpecificScore: appScore, DecayInterval: time.Second, DecayToZero: 0.01, BehaviourPenaltyWeight: -1}).validate() == nil {
|
|
||||||
t.Fatal("expected validation error")
|
|
||||||
}
|
|
||||||
if (&PeerScoreParams{AppSpecificScore: appScore, DecayInterval: time.Second, DecayToZero: 0.01, BehaviourPenaltyWeight: -1, BehaviourPenaltyDecay: 2}).validate() == nil {
|
|
||||||
t.Fatal("expected validation error")
|
|
||||||
}
|
|
||||||
|
|
||||||
// don't use these params in production!
|
|
||||||
if (&PeerScoreParams{
|
if (&PeerScoreParams{
|
||||||
AppSpecificScore: appScore,
|
SkipAtomicValidation: skipAtomicValidation,
|
||||||
DecayInterval: time.Second,
|
TopicScoreCap: -1,
|
||||||
DecayToZero: 0.01,
|
AppSpecificScore: appScore,
|
||||||
IPColocationFactorWeight: -1,
|
DecayInterval: time.Second,
|
||||||
IPColocationFactorThreshold: 1,
|
DecayToZero: 0.01,
|
||||||
BehaviourPenaltyWeight: -1,
|
|
||||||
BehaviourPenaltyDecay: 0.999,
|
|
||||||
}).validate() != nil {
|
|
||||||
t.Fatal("expected validation success")
|
|
||||||
}
|
|
||||||
|
|
||||||
if (&PeerScoreParams{
|
|
||||||
TopicScoreCap: 1,
|
|
||||||
AppSpecificScore: appScore,
|
|
||||||
DecayInterval: time.Second,
|
|
||||||
DecayToZero: 0.01,
|
|
||||||
IPColocationFactorWeight: -1,
|
|
||||||
IPColocationFactorThreshold: 1,
|
|
||||||
BehaviourPenaltyWeight: -1,
|
|
||||||
BehaviourPenaltyDecay: 0.999,
|
|
||||||
}).validate() != nil {
|
|
||||||
t.Fatal("expected validation success")
|
|
||||||
}
|
|
||||||
|
|
||||||
if (&PeerScoreParams{
|
|
||||||
TopicScoreCap: 1,
|
|
||||||
AppSpecificScore: appScore,
|
|
||||||
DecayInterval: time.Second,
|
|
||||||
DecayToZero: 0.01,
|
|
||||||
IPColocationFactorWeight: -1,
|
|
||||||
IPColocationFactorThreshold: 1,
|
|
||||||
Topics: map[string]*TopicScoreParams{
|
|
||||||
"test": &TopicScoreParams{
|
|
||||||
TopicWeight: 1,
|
|
||||||
TimeInMeshWeight: 0.01,
|
|
||||||
TimeInMeshQuantum: time.Second,
|
|
||||||
TimeInMeshCap: 10,
|
|
||||||
FirstMessageDeliveriesWeight: 1,
|
|
||||||
FirstMessageDeliveriesDecay: 0.5,
|
|
||||||
FirstMessageDeliveriesCap: 10,
|
|
||||||
MeshMessageDeliveriesWeight: -1,
|
|
||||||
MeshMessageDeliveriesDecay: 0.5,
|
|
||||||
MeshMessageDeliveriesCap: 10,
|
|
||||||
MeshMessageDeliveriesThreshold: 5,
|
|
||||||
MeshMessageDeliveriesWindow: time.Millisecond,
|
|
||||||
MeshMessageDeliveriesActivation: time.Second,
|
|
||||||
MeshFailurePenaltyWeight: -1,
|
|
||||||
MeshFailurePenaltyDecay: 0.5,
|
|
||||||
InvalidMessageDeliveriesWeight: -1,
|
|
||||||
InvalidMessageDeliveriesDecay: 0.5,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
}).validate() != nil {
|
|
||||||
t.Fatal("expected validation success")
|
|
||||||
}
|
|
||||||
|
|
||||||
// don't use these params in production!
|
|
||||||
if (&PeerScoreParams{
|
|
||||||
TopicScoreCap: 1,
|
|
||||||
AppSpecificScore: appScore,
|
|
||||||
DecayInterval: time.Second,
|
|
||||||
DecayToZero: 0.01,
|
|
||||||
IPColocationFactorWeight: -1,
|
|
||||||
IPColocationFactorThreshold: 1,
|
|
||||||
Topics: map[string]*TopicScoreParams{
|
|
||||||
"test": &TopicScoreParams{
|
|
||||||
TopicWeight: -1,
|
|
||||||
TimeInMeshWeight: 0.01,
|
|
||||||
TimeInMeshQuantum: time.Second,
|
|
||||||
TimeInMeshCap: 10,
|
|
||||||
FirstMessageDeliveriesWeight: 1,
|
|
||||||
FirstMessageDeliveriesDecay: 0.5,
|
|
||||||
FirstMessageDeliveriesCap: 10,
|
|
||||||
MeshMessageDeliveriesWeight: -1,
|
|
||||||
MeshMessageDeliveriesDecay: 0.5,
|
|
||||||
MeshMessageDeliveriesCap: 10,
|
|
||||||
MeshMessageDeliveriesThreshold: 5,
|
|
||||||
MeshMessageDeliveriesWindow: time.Millisecond,
|
|
||||||
MeshMessageDeliveriesActivation: time.Second,
|
|
||||||
MeshFailurePenaltyWeight: -1,
|
|
||||||
MeshFailurePenaltyDecay: 0.5,
|
|
||||||
InvalidMessageDeliveriesWeight: -1,
|
|
||||||
InvalidMessageDeliveriesDecay: 0.5,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
}).validate() == nil {
|
}).validate() == nil {
|
||||||
t.Fatal("expected validation failure")
|
t.Fatal("expected validation error")
|
||||||
|
}
|
||||||
|
|
||||||
|
if skipAtomicValidation {
|
||||||
|
if (&PeerScoreParams{
|
||||||
|
SkipAtomicValidation: skipAtomicValidation,
|
||||||
|
TopicScoreCap: 1,
|
||||||
|
DecayInterval: time.Second,
|
||||||
|
DecayToZero: 0.01,
|
||||||
|
}).validate() != nil {
|
||||||
|
t.Fatal("expected validation success")
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (&PeerScoreParams{
|
||||||
|
SkipAtomicValidation: skipAtomicValidation,
|
||||||
|
TopicScoreCap: 1,
|
||||||
|
DecayInterval: time.Second,
|
||||||
|
DecayToZero: 0.01,
|
||||||
|
}).validate() == nil {
|
||||||
|
t.Fatal("expected validation error")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (&PeerScoreParams{
|
||||||
|
SkipAtomicValidation: skipAtomicValidation,
|
||||||
|
TopicScoreCap: 1,
|
||||||
|
AppSpecificScore: appScore,
|
||||||
|
DecayInterval: time.Second,
|
||||||
|
DecayToZero: 0.01,
|
||||||
|
IPColocationFactorWeight: 1,
|
||||||
|
}).validate() == nil {
|
||||||
|
t.Fatal("expected validation error")
|
||||||
|
}
|
||||||
|
if (&PeerScoreParams{
|
||||||
|
SkipAtomicValidation: skipAtomicValidation,
|
||||||
|
TopicScoreCap: 1,
|
||||||
|
AppSpecificScore: appScore,
|
||||||
|
DecayInterval: time.Second,
|
||||||
|
DecayToZero: 0.01,
|
||||||
|
IPColocationFactorWeight: -1,
|
||||||
|
IPColocationFactorThreshold: -1}).validate() == nil {
|
||||||
|
t.Fatal("expected validation error")
|
||||||
|
}
|
||||||
|
if (&PeerScoreParams{
|
||||||
|
SkipAtomicValidation: skipAtomicValidation,
|
||||||
|
TopicScoreCap: 1,
|
||||||
|
AppSpecificScore: appScore,
|
||||||
|
DecayInterval: time.Millisecond,
|
||||||
|
DecayToZero: 0.01,
|
||||||
|
IPColocationFactorWeight: -1,
|
||||||
|
IPColocationFactorThreshold: 1,
|
||||||
|
}).validate() == nil {
|
||||||
|
t.Fatal("expected validation error")
|
||||||
|
}
|
||||||
|
if (&PeerScoreParams{
|
||||||
|
SkipAtomicValidation: skipAtomicValidation,
|
||||||
|
TopicScoreCap: 1,
|
||||||
|
AppSpecificScore: appScore,
|
||||||
|
DecayInterval: time.Second,
|
||||||
|
DecayToZero: -1,
|
||||||
|
IPColocationFactorWeight: -1,
|
||||||
|
IPColocationFactorThreshold: 1,
|
||||||
|
}).validate() == nil {
|
||||||
|
t.Fatal("expected validation error")
|
||||||
|
}
|
||||||
|
if (&PeerScoreParams{
|
||||||
|
SkipAtomicValidation: skipAtomicValidation,
|
||||||
|
TopicScoreCap: 1,
|
||||||
|
AppSpecificScore: appScore,
|
||||||
|
DecayInterval: time.Second,
|
||||||
|
DecayToZero: 2,
|
||||||
|
IPColocationFactorWeight: -1,
|
||||||
|
IPColocationFactorThreshold: 1,
|
||||||
|
}).validate() == nil {
|
||||||
|
t.Fatal("expected validation error")
|
||||||
|
}
|
||||||
|
if (&PeerScoreParams{
|
||||||
|
SkipAtomicValidation: skipAtomicValidation,
|
||||||
|
AppSpecificScore: appScore,
|
||||||
|
DecayInterval: time.Second,
|
||||||
|
DecayToZero: 0.01,
|
||||||
|
BehaviourPenaltyWeight: 1}).validate() == nil {
|
||||||
|
t.Fatal("expected validation error")
|
||||||
|
}
|
||||||
|
if (&PeerScoreParams{
|
||||||
|
SkipAtomicValidation: skipAtomicValidation,
|
||||||
|
AppSpecificScore: appScore,
|
||||||
|
DecayInterval: time.Second,
|
||||||
|
DecayToZero: 0.01,
|
||||||
|
BehaviourPenaltyWeight: -1,
|
||||||
|
}).validate() == nil {
|
||||||
|
t.Fatal("expected validation error")
|
||||||
|
}
|
||||||
|
if (&PeerScoreParams{
|
||||||
|
SkipAtomicValidation: skipAtomicValidation,
|
||||||
|
AppSpecificScore: appScore,
|
||||||
|
DecayInterval: time.Second,
|
||||||
|
DecayToZero: 0.01,
|
||||||
|
BehaviourPenaltyWeight: -1,
|
||||||
|
BehaviourPenaltyDecay: 2,
|
||||||
|
}).validate() == nil {
|
||||||
|
t.Fatal("expected validation error")
|
||||||
}
|
}
|
||||||
|
|
||||||
// Checks the topic parameters for invalid values such as infinite and
|
// Checks the topic parameters for invalid values such as infinite and
|
||||||
// NaN numbers.
|
// NaN numbers.
|
||||||
|
|
||||||
// Don't use these params in production!
|
|
||||||
if (&PeerScoreParams{
|
|
||||||
AppSpecificScore: appScore,
|
|
||||||
DecayInterval: time.Second,
|
|
||||||
DecayToZero: math.Inf(0),
|
|
||||||
IPColocationFactorWeight: math.Inf(-1),
|
|
||||||
IPColocationFactorThreshold: 1,
|
|
||||||
BehaviourPenaltyWeight: math.Inf(0),
|
|
||||||
BehaviourPenaltyDecay: math.NaN(),
|
|
||||||
}).validate() == nil {
|
|
||||||
t.Fatal("expected validation failure")
|
|
||||||
}
|
|
||||||
|
|
||||||
if (&PeerScoreParams{
|
if (&PeerScoreParams{
|
||||||
|
SkipAtomicValidation: skipAtomicValidation,
|
||||||
TopicScoreCap: 1,
|
TopicScoreCap: 1,
|
||||||
AppSpecificScore: appScore,
|
AppSpecificScore: appScore,
|
||||||
DecayInterval: time.Second,
|
DecayInterval: time.Second,
|
||||||
@ -294,7 +519,7 @@ func TestPeerScoreParamsValidation(t *testing.T) {
|
|||||||
IPColocationFactorWeight: -1,
|
IPColocationFactorWeight: -1,
|
||||||
IPColocationFactorThreshold: 1,
|
IPColocationFactorThreshold: 1,
|
||||||
Topics: map[string]*TopicScoreParams{
|
Topics: map[string]*TopicScoreParams{
|
||||||
"test": &TopicScoreParams{
|
"test": {
|
||||||
TopicWeight: math.Inf(0),
|
TopicWeight: math.Inf(0),
|
||||||
TimeInMeshWeight: math.NaN(),
|
TimeInMeshWeight: math.NaN(),
|
||||||
TimeInMeshQuantum: time.Second,
|
TimeInMeshQuantum: time.Second,
|
||||||
@ -318,6 +543,178 @@ func TestPeerScoreParamsValidation(t *testing.T) {
|
|||||||
t.Fatal("expected validation failure")
|
t.Fatal("expected validation failure")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (&PeerScoreParams{
|
||||||
|
SkipAtomicValidation: skipAtomicValidation,
|
||||||
|
AppSpecificScore: appScore,
|
||||||
|
DecayInterval: time.Second,
|
||||||
|
DecayToZero: math.Inf(0),
|
||||||
|
IPColocationFactorWeight: math.Inf(-1),
|
||||||
|
IPColocationFactorThreshold: 1,
|
||||||
|
BehaviourPenaltyWeight: math.Inf(0),
|
||||||
|
BehaviourPenaltyDecay: math.NaN(),
|
||||||
|
}).validate() == nil {
|
||||||
|
t.Fatal("expected validation failure")
|
||||||
|
}
|
||||||
|
|
||||||
|
if (&PeerScoreParams{
|
||||||
|
SkipAtomicValidation: skipAtomicValidation,
|
||||||
|
TopicScoreCap: 1,
|
||||||
|
AppSpecificScore: appScore,
|
||||||
|
DecayInterval: time.Second,
|
||||||
|
DecayToZero: 0.01,
|
||||||
|
IPColocationFactorWeight: -1,
|
||||||
|
IPColocationFactorThreshold: 1,
|
||||||
|
Topics: map[string]*TopicScoreParams{
|
||||||
|
"test": {
|
||||||
|
TopicWeight: -1,
|
||||||
|
TimeInMeshWeight: 0.01,
|
||||||
|
TimeInMeshQuantum: time.Second,
|
||||||
|
TimeInMeshCap: 10,
|
||||||
|
FirstMessageDeliveriesWeight: 1,
|
||||||
|
FirstMessageDeliveriesDecay: 0.5,
|
||||||
|
FirstMessageDeliveriesCap: 10,
|
||||||
|
MeshMessageDeliveriesWeight: -1,
|
||||||
|
MeshMessageDeliveriesDecay: 0.5,
|
||||||
|
MeshMessageDeliveriesCap: 10,
|
||||||
|
MeshMessageDeliveriesThreshold: 5,
|
||||||
|
MeshMessageDeliveriesWindow: time.Millisecond,
|
||||||
|
MeshMessageDeliveriesActivation: time.Second,
|
||||||
|
MeshFailurePenaltyWeight: -1,
|
||||||
|
MeshFailurePenaltyDecay: 0.5,
|
||||||
|
InvalidMessageDeliveriesWeight: -1,
|
||||||
|
InvalidMessageDeliveriesDecay: 0.5,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}).validate() == nil {
|
||||||
|
t.Fatal("expected validation failure")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestPeerScoreParamsValidation_ValidParams_AtomicValidation(t *testing.T) {
|
||||||
|
appScore := func(peer.ID) float64 { return 0 }
|
||||||
|
|
||||||
|
// don't use these params in production!
|
||||||
|
if (&PeerScoreParams{
|
||||||
|
AppSpecificScore: appScore,
|
||||||
|
DecayInterval: time.Second,
|
||||||
|
DecayToZero: 0.01,
|
||||||
|
IPColocationFactorWeight: -1,
|
||||||
|
IPColocationFactorThreshold: 1,
|
||||||
|
BehaviourPenaltyWeight: -1,
|
||||||
|
BehaviourPenaltyDecay: 0.999,
|
||||||
|
}).validate() != nil {
|
||||||
|
t.Fatal("expected validation success")
|
||||||
|
}
|
||||||
|
|
||||||
|
if (&PeerScoreParams{
|
||||||
|
TopicScoreCap: 1,
|
||||||
|
AppSpecificScore: appScore,
|
||||||
|
DecayInterval: time.Second,
|
||||||
|
DecayToZero: 0.01,
|
||||||
|
IPColocationFactorWeight: -1,
|
||||||
|
IPColocationFactorThreshold: 1,
|
||||||
|
BehaviourPenaltyWeight: -1,
|
||||||
|
BehaviourPenaltyDecay: 0.999,
|
||||||
|
}).validate() != nil {
|
||||||
|
t.Fatal("expected validation success")
|
||||||
|
}
|
||||||
|
|
||||||
|
if (&PeerScoreParams{
|
||||||
|
TopicScoreCap: 1,
|
||||||
|
AppSpecificScore: appScore,
|
||||||
|
DecayInterval: time.Second,
|
||||||
|
DecayToZero: 0.01,
|
||||||
|
IPColocationFactorWeight: -1,
|
||||||
|
IPColocationFactorThreshold: 1,
|
||||||
|
Topics: map[string]*TopicScoreParams{
|
||||||
|
"test": {
|
||||||
|
TopicWeight: 1,
|
||||||
|
TimeInMeshWeight: 0.01,
|
||||||
|
TimeInMeshQuantum: time.Second,
|
||||||
|
TimeInMeshCap: 10,
|
||||||
|
FirstMessageDeliveriesWeight: 1,
|
||||||
|
FirstMessageDeliveriesDecay: 0.5,
|
||||||
|
FirstMessageDeliveriesCap: 10,
|
||||||
|
MeshMessageDeliveriesWeight: -1,
|
||||||
|
MeshMessageDeliveriesDecay: 0.5,
|
||||||
|
MeshMessageDeliveriesCap: 10,
|
||||||
|
MeshMessageDeliveriesThreshold: 5,
|
||||||
|
MeshMessageDeliveriesWindow: time.Millisecond,
|
||||||
|
MeshMessageDeliveriesActivation: time.Second,
|
||||||
|
MeshFailurePenaltyWeight: -1,
|
||||||
|
MeshFailurePenaltyDecay: 0.5,
|
||||||
|
InvalidMessageDeliveriesWeight: -1,
|
||||||
|
InvalidMessageDeliveriesDecay: 0.5,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}).validate() != nil {
|
||||||
|
t.Fatal("expected validation success")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestPeerScoreParamsValidation_ValidParams_SkipAtomicValidation(t *testing.T) {
|
||||||
|
appScore := func(peer.ID) float64 { return 0 }
|
||||||
|
|
||||||
|
// don't use these params in production!
|
||||||
|
p := &PeerScoreParams{}
|
||||||
|
setParamAndValidate(t, p, func(params *PeerScoreParams) {
|
||||||
|
params.SkipAtomicValidation = true
|
||||||
|
})
|
||||||
|
setParamAndValidate(t, p, func(params *PeerScoreParams) {
|
||||||
|
params.AppSpecificScore = appScore
|
||||||
|
})
|
||||||
|
setParamAndValidate(t, p, func(params *PeerScoreParams) {
|
||||||
|
params.DecayInterval = time.Second
|
||||||
|
params.DecayToZero = 0.01
|
||||||
|
})
|
||||||
|
setParamAndValidate(t, p, func(params *PeerScoreParams) {
|
||||||
|
params.IPColocationFactorWeight = -1
|
||||||
|
params.IPColocationFactorThreshold = 1
|
||||||
|
})
|
||||||
|
setParamAndValidate(t, p, func(params *PeerScoreParams) {
|
||||||
|
params.BehaviourPenaltyWeight = -1
|
||||||
|
params.BehaviourPenaltyDecay = 0.999
|
||||||
|
})
|
||||||
|
|
||||||
|
p = &PeerScoreParams{SkipAtomicValidation: true, AppSpecificScore: appScore}
|
||||||
|
setParamAndValidate(t, p, func(params *PeerScoreParams) {
|
||||||
|
params.TopicScoreCap = 1
|
||||||
|
})
|
||||||
|
setParamAndValidate(t, p, func(params *PeerScoreParams) {
|
||||||
|
params.DecayInterval = time.Second
|
||||||
|
params.DecayToZero = 0.01
|
||||||
|
})
|
||||||
|
setParamAndValidate(t, p, func(params *PeerScoreParams) {
|
||||||
|
params.IPColocationFactorWeight = -1
|
||||||
|
params.IPColocationFactorThreshold = 1
|
||||||
|
})
|
||||||
|
setParamAndValidate(t, p, func(params *PeerScoreParams) {
|
||||||
|
params.BehaviourPenaltyWeight = -1
|
||||||
|
params.BehaviourPenaltyDecay = 0.999
|
||||||
|
})
|
||||||
|
setParamAndValidate(t, p, func(params *PeerScoreParams) {
|
||||||
|
params.Topics = map[string]*TopicScoreParams{
|
||||||
|
"test": {
|
||||||
|
TopicWeight: 1,
|
||||||
|
TimeInMeshWeight: 0.01,
|
||||||
|
TimeInMeshQuantum: time.Second,
|
||||||
|
TimeInMeshCap: 10,
|
||||||
|
FirstMessageDeliveriesWeight: 1,
|
||||||
|
FirstMessageDeliveriesDecay: 0.5,
|
||||||
|
FirstMessageDeliveriesCap: 10,
|
||||||
|
MeshMessageDeliveriesWeight: -1,
|
||||||
|
MeshMessageDeliveriesDecay: 0.5,
|
||||||
|
MeshMessageDeliveriesCap: 10,
|
||||||
|
MeshMessageDeliveriesThreshold: 5,
|
||||||
|
MeshMessageDeliveriesWindow: time.Millisecond,
|
||||||
|
MeshMessageDeliveriesActivation: time.Second,
|
||||||
|
MeshFailurePenaltyWeight: -1,
|
||||||
|
MeshFailurePenaltyDecay: 0.5,
|
||||||
|
InvalidMessageDeliveriesWeight: -1,
|
||||||
|
InvalidMessageDeliveriesDecay: 0.5,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestScoreParameterDecay(t *testing.T) {
|
func TestScoreParameterDecay(t *testing.T) {
|
||||||
@ -326,3 +723,17 @@ func TestScoreParameterDecay(t *testing.T) {
|
|||||||
t.Fatalf("expected .9987216039048303, got %f", decay1hr)
|
t.Fatalf("expected .9987216039048303, got %f", decay1hr)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func setParamAndValidate(t *testing.T, params *PeerScoreParams, set func(*PeerScoreParams)) {
|
||||||
|
set(params)
|
||||||
|
if err := params.validate(); err != nil {
|
||||||
|
t.Fatalf("expected validation success, got: %s", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func setTopicParamAndValidate(t *testing.T, params *TopicScoreParams, set func(topic *TopicScoreParams)) {
|
||||||
|
set(params)
|
||||||
|
if err := params.validate(); err != nil {
|
||||||
|
t.Fatalf("expected validation success, got: %s", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user