storj/cmd/tools/segment-verify/nodealias_test.go
paul cannon 2feb49afc3 cmd/tools/segment-verify: don't cache offline status forever
Because it was originally intended to work on only a few pieces from
each segment at a time, and would frequently have reset its list of
online nodes, segment-verify has been taking nodes out of its
onlineNodes set and never putting them back. This means that over a long
run in Check=0 mode, we end up treating more and more nodes as offline,
permanently. This trend obfuscates the number of missing pieces that
each segment really has, because we don't check pieces on offline nodes.

This commit changes the onlineNodes set to an "offlineNodes" set, with
an expiration time on the offline-ness quality. So nodes are added to
the offlineNodes set when we see they are offline, and then we only
treat them as offline for the next 30 minutes (configurable). After that
point, we will try connecting to them again.

Change-Id: I14f0332de25cdc6ef655f923739bcb4df71e079e
2023-01-03 23:11:42 +00:00

120 lines
2.8 KiB
Go

// Copyright (C) 2023 Storj Labs, Inc.
// See LICENSE for copying information.
package main
import (
"testing"
"time"
"github.com/stretchr/testify/assert"
"storj.io/common/testrand"
"storj.io/storj/satellite/metabase"
)
func randomNodeAlias() metabase.NodeAlias {
return metabase.NodeAlias(testrand.Intn(65536))
}
func TestNodeAliasExpiringSetAddAndRemove(t *testing.T) {
// choose 3 random and unique aliases
alias1 := randomNodeAlias()
alias2 := alias1
for alias2 == alias1 {
alias2 = randomNodeAlias()
}
alias3 := alias1
for alias3 == alias1 || alias3 == alias2 {
alias3 = randomNodeAlias()
}
// add them to a nodeAliasExpiringSet one at a time
set := newNodeAliasExpiringSet(24 * time.Hour)
assert.False(t, set.Contains(alias1))
assert.False(t, set.Contains(alias2))
assert.False(t, set.Contains(alias3))
set.Add(alias1)
assert.True(t, set.Contains(alias1))
assert.False(t, set.Contains(alias2))
assert.False(t, set.Contains(alias3))
set.Add(alias2)
assert.True(t, set.Contains(alias1))
assert.True(t, set.Contains(alias2))
assert.False(t, set.Contains(alias3))
set.Add(alias3)
assert.True(t, set.Contains(alias1))
assert.True(t, set.Contains(alias2))
assert.True(t, set.Contains(alias3))
// then remove one at a time
set.Remove(alias2)
assert.True(t, set.Contains(alias1))
assert.False(t, set.Contains(alias2))
assert.True(t, set.Contains(alias3))
set.Remove(alias2) // again; should have no effect this time
assert.True(t, set.Contains(alias1))
assert.False(t, set.Contains(alias2))
assert.True(t, set.Contains(alias3))
set.Remove(alias1)
assert.False(t, set.Contains(alias1))
assert.False(t, set.Contains(alias2))
assert.True(t, set.Contains(alias3))
set.Remove(alias3)
assert.False(t, set.Contains(alias1))
assert.False(t, set.Contains(alias2))
assert.False(t, set.Contains(alias3))
}
type dummyTime struct {
time.Time
}
func (dt *dummyTime) Elapse(d time.Duration) {
dt.Time = dt.Time.Add(d)
}
func (dt *dummyTime) Get() time.Time {
return dt.Time
}
func TestNodeAliasExpiringSetExpiration(t *testing.T) {
mockTime := dummyTime{time.Now()}
set := newNodeAliasExpiringSet(time.Minute)
set.nowFunc = mockTime.Get
alias1 := randomNodeAlias()
alias2 := alias1
for alias2 == alias1 {
alias2 = randomNodeAlias()
}
set.Add(alias1)
assert.True(t, set.Contains(alias1))
assert.False(t, set.Contains(alias2))
mockTime.Elapse(30 * time.Second)
assert.True(t, set.Contains(alias1))
assert.False(t, set.Contains(alias2))
set.Add(alias2)
assert.True(t, set.Contains(alias1))
assert.True(t, set.Contains(alias2))
mockTime.Elapse(31 * time.Second)
assert.False(t, set.Contains(alias1))
assert.True(t, set.Contains(alias2))
mockTime.Elapse(30 * time.Second)
assert.False(t, set.Contains(alias1))
assert.False(t, set.Contains(alias2))
}