Commit 1e5a6e7d authored by Andreas Bigger's avatar Andreas Bigger

fix nits

parent d645fab0
...@@ -9,19 +9,71 @@ import ( ...@@ -9,19 +9,71 @@ import (
// TestBandScorer_ParseDefault tests the [BandScorer.Parse] function // TestBandScorer_ParseDefault tests the [BandScorer.Parse] function
// on the default band scores cli flag value. // on the default band scores cli flag value.
func TestBandScorer_ParseDefault(t *testing.T) { func TestBandScorer_ParseDefault(t *testing.T) {
defaultScoringBands := "-40:graylist;-20:restricted;0:nopx;20:friend;" // Create a new band scorer.
bandScorer := NewBandScorer()
require.NoError(t, bandScorer.Parse("-40:graylist;-20:restricted;0:nopx;20:friend;"))
// Validate the [BandScorer] internals.
require.ElementsMatch(t, bandScorer.bands, []scorePair{
{band: "graylist", threshold: -40},
{band: "restricted", threshold: -20},
{band: "nopx", threshold: 0},
{band: "friend", threshold: 20},
})
}
// TestBandScorer_BucketCorrectly tests the [BandScorer.Bucket] function
// on a variety of scores.
func TestBandScorer_BucketCorrectly(t *testing.T) {
// Create a new band scorer. // Create a new band scorer.
bandScorer := NewBandScorer() bandScorer := NewBandScorer()
require.NoError(t, bandScorer.Parse(defaultScoringBands)) require.NoError(t, bandScorer.Parse("-40:graylist;-20:restricted;0:nopx;20:friend;"))
// Let's validate that the [BandScorer] sorts the bands correctly.
require.Equal(t, bandScorer.bands, []scorePair{
{band: "graylist", threshold: -40},
{band: "restricted", threshold: -20},
{band: "nopx", threshold: 0},
{band: "friend", threshold: 20},
})
// Validate the [BandScorer] internals.
require.Equal(t, bandScorer.Bucket(-100), "graylist")
require.Equal(t, bandScorer.Bucket(-40), "graylist")
require.Equal(t, bandScorer.Bucket(-39), "restricted")
require.Equal(t, bandScorer.Bucket(-20), "restricted")
require.Equal(t, bandScorer.Bucket(-19), "nopx")
require.Equal(t, bandScorer.Bucket(0), "nopx")
require.Equal(t, bandScorer.Bucket(1), "friend")
require.Equal(t, bandScorer.Bucket(20), "friend")
require.Equal(t, bandScorer.Bucket(21), "friend")
}
// TestBandScorer_BucketInverted tests the [BandScorer.Bucket] function
// on a variety of scores, in descending order.
func TestBandScorer_BucketInverted(t *testing.T) {
// Create a new band scorer.
bandScorer := NewBandScorer()
require.NoError(t, bandScorer.Parse("20:friend;0:nopx;-20:restricted;-40:graylist;"))
// Let's validate that the [BandScorer] sorts the bands correctly.
require.Equal(t, bandScorer.bands, []scorePair{
{band: "graylist", threshold: -40},
{band: "restricted", threshold: -20},
{band: "nopx", threshold: 0},
{band: "friend", threshold: 20},
})
// Validate the [BandScorer] internals. // Validate the [BandScorer] internals.
require.Len(t, bandScorer.(*bandScoreThresholds).bands, 4) require.Equal(t, bandScorer.Bucket(-100), "graylist")
require.Equal(t, bandScorer.(*bandScoreThresholds).bands["graylist"], float64(-40)) require.Equal(t, bandScorer.Bucket(-40), "graylist")
require.Equal(t, bandScorer.(*bandScoreThresholds).bands["restricted"], float64(-20)) require.Equal(t, bandScorer.Bucket(-39), "restricted")
require.Equal(t, bandScorer.(*bandScoreThresholds).bands["nopx"], float64(0)) require.Equal(t, bandScorer.Bucket(-20), "restricted")
require.Equal(t, bandScorer.(*bandScoreThresholds).bands["friend"], float64(20)) require.Equal(t, bandScorer.Bucket(-19), "nopx")
require.Equal(t, bandScorer.(*bandScoreThresholds).lowestBand, "graylist") require.Equal(t, bandScorer.Bucket(0), "nopx")
require.Equal(t, bandScorer.Bucket(1), "friend")
require.Equal(t, bandScorer.Bucket(20), "friend")
require.Equal(t, bandScorer.Bucket(21), "friend")
} }
// TestBandScorer_ParseEmpty tests the [BandScorer.Parse] function // TestBandScorer_ParseEmpty tests the [BandScorer.Parse] function
...@@ -32,12 +84,7 @@ func TestBandScorer_ParseEmpty(t *testing.T) { ...@@ -32,12 +84,7 @@ func TestBandScorer_ParseEmpty(t *testing.T) {
require.NoError(t, bandScorer.Parse("")) require.NoError(t, bandScorer.Parse(""))
// Validate the [BandScorer] internals. // Validate the [BandScorer] internals.
require.Len(t, bandScorer.(*bandScoreThresholds).bands, 0) require.Len(t, bandScorer.bands, 0)
require.Equal(t, bandScorer.(*bandScoreThresholds).bands["graylist"], float64(0))
require.Equal(t, bandScorer.(*bandScoreThresholds).bands["restricted"], float64(0))
require.Equal(t, bandScorer.(*bandScoreThresholds).bands["nopx"], float64(0))
require.Equal(t, bandScorer.(*bandScoreThresholds).bands["friend"], float64(0))
require.Equal(t, bandScorer.(*bandScoreThresholds).lowestBand, "")
} }
// TestBandScorer_ParseWhitespace tests the [BandScorer.Parse] function // TestBandScorer_ParseWhitespace tests the [BandScorer.Parse] function
...@@ -48,10 +95,5 @@ func TestBandScorer_ParseWhitespace(t *testing.T) { ...@@ -48,10 +95,5 @@ func TestBandScorer_ParseWhitespace(t *testing.T) {
require.NoError(t, bandScorer.Parse(" ; ; ; ")) require.NoError(t, bandScorer.Parse(" ; ; ; "))
// Validate the [BandScorer] internals. // Validate the [BandScorer] internals.
require.Len(t, bandScorer.(*bandScoreThresholds).bands, 0) require.Len(t, bandScorer.bands, 0)
require.Equal(t, bandScorer.(*bandScoreThresholds).bands["graylist"], float64(0))
require.Equal(t, bandScorer.(*bandScoreThresholds).bands["restricted"], float64(0))
require.Equal(t, bandScorer.(*bandScoreThresholds).bands["nopx"], float64(0))
require.Equal(t, bandScorer.(*bandScoreThresholds).bands["friend"], float64(0))
require.Equal(t, bandScorer.(*bandScoreThresholds).lowestBand, "")
} }
...@@ -2,6 +2,7 @@ package p2p ...@@ -2,6 +2,7 @@ package p2p
import ( import (
"fmt" "fmt"
"sort"
"strconv" "strconv"
"strings" "strings"
...@@ -18,11 +19,15 @@ type scorer struct { ...@@ -18,11 +19,15 @@ type scorer struct {
bandScoreThresholds BandScorer bandScoreThresholds BandScorer
} }
// bandScoreThresholds holds the thresholds for classifying peers type scorePair struct {
band string
threshold float64
}
// BandScoreThresholds holds the thresholds for classifying peers
// into different score bands. // into different score bands.
type bandScoreThresholds struct { type BandScoreThresholds struct {
bands map[string]float64 bands []scorePair
lowestBand string
} }
// BandScorer is an interface for placing peer scores // BandScorer is an interface for placing peer scores
...@@ -40,21 +45,20 @@ type BandScorer interface { ...@@ -40,21 +45,20 @@ type BandScorer interface {
} }
// NewBandScorer constructs a new [BandScorer] instance. // NewBandScorer constructs a new [BandScorer] instance.
func NewBandScorer() BandScorer { func NewBandScorer() *BandScoreThresholds {
return &bandScoreThresholds{ return &BandScoreThresholds{
bands: make(map[string]float64), bands: make([]scorePair, 0),
} }
} }
// Reset wipes the internal state of the [BandScorer]. // Reset wipes the internal state of the [BandScorer].
func (s *bandScoreThresholds) Reset() { func (s *BandScoreThresholds) Reset() {
s.bands = make(map[string]float64) s.bands = s.bands[:0]
} }
// Parse creates a [BandScorer] from a given string. // Parse creates a [BandScorer] from a given string.
func (s *bandScoreThresholds) Parse(str string) error { func (s *BandScoreThresholds) Parse(str string) error {
var lowestThreshold float64 for _, band := range strings.Split(str, ";") {
for i, band := range strings.Split(str, ";") {
// Skip empty band strings. // Skip empty band strings.
band := strings.TrimSpace(band) band := strings.TrimSpace(band)
if band == "" { if band == "" {
...@@ -68,25 +72,33 @@ func (s *bandScoreThresholds) Parse(str string) error { ...@@ -68,25 +72,33 @@ func (s *bandScoreThresholds) Parse(str string) error {
if err != nil { if err != nil {
return err return err
} }
s.bands[split[1]] = threshold s.bands = append(s.bands, scorePair{
if threshold < lowestThreshold || i == 0 { band: split[1],
s.lowestBand = split[1] threshold: threshold,
lowestThreshold = threshold })
}
} }
// Order the bands by threshold in ascending order.
sort.Slice(s.bands, func(i, j int) bool {
return s.bands[i].threshold < s.bands[j].threshold
})
return nil return nil
} }
// Bucket returns the appropriate band for a given score. // Bucket returns the appropriate band for a given score.
func (s *bandScoreThresholds) Bucket(score float64) string { func (s *BandScoreThresholds) Bucket(score float64) string {
for band, threshold := range s.bands { for _, pair := range s.bands {
if score >= threshold { if score <= pair.threshold {
return band return pair.band
} }
} }
// If there is no band threshold lower than the score, // If there is no band threshold higher than the score,
// the peer must be placed in the lowest bucket. // the peer must be placed in the highest bucket.
return s.lowestBand if len(s.bands) > 0 {
return s.bands[len(s.bands)-1].band
}
return ""
} }
// Peerstore is a subset of the libp2p peerstore.Peerstore interface. // Peerstore is a subset of the libp2p peerstore.Peerstore interface.
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment