frostfs-node/pkg/morph/timer/block_test.go

173 lines
3.5 KiB
Go
Raw Normal View History

package timer_test
import (
"errors"
"testing"
"git.frostfs.info/TrueCloudLab/frostfs-node/pkg/morph/timer"
"github.com/stretchr/testify/require"
)
func tickN(t *timer.BlockTimer, n uint32) {
for range n {
t.Tick(0)
}
}
// This test emulates inner ring handling of a new epoch and a new block.
// "resetting" consists of ticking the current height as well and invoking `Reset`.
func TestIRBlockTimer_Reset(t *testing.T) {
var baseCounter [2]int
blockDur := uint32(3)
bt1 := timer.NewBlockTimer(
func() (uint32, error) { return blockDur, nil },
func() { baseCounter[0]++ })
bt2 := timer.NewBlockTimer(
func() (uint32, error) { return blockDur, nil },
func() { baseCounter[1]++ })
require.NoError(t, bt1.Reset())
require.NoError(t, bt2.Reset())
run := func(bt *timer.BlockTimer, direct bool) {
if direct {
bt.Tick(1)
require.NoError(t, bt.Reset())
bt.Tick(1)
} else {
bt.Tick(1)
bt.Tick(1)
require.NoError(t, bt.Reset())
}
bt.Tick(2)
bt.Tick(3)
}
run(bt1, true)
run(bt2, false)
require.Equal(t, baseCounter[0], baseCounter[1])
}
func TestBlockTimer_ResetChangeDuration(t *testing.T) {
var dur uint32 = 2
var err error
var counter int
bt := timer.NewBlockTimer(
func() (uint32, error) { return dur, err },
func() { counter++ })
require.NoError(t, bt.Reset())
tickN(bt, 2)
require.Equal(t, 1, counter)
t.Run("return error", func(t *testing.T) {
dur = 5
err = errors.New("my awesome error")
require.ErrorIs(t, bt.Reset(), err)
tickN(bt, 2)
require.Equal(t, 2, counter)
})
t.Run("change duration", func(t *testing.T) {
dur = 5
err = nil
require.NoError(t, bt.Reset())
tickN(bt, 5)
require.Equal(t, 3, counter)
})
}
func TestBlockTimer(t *testing.T) {
blockDur := uint32(10)
baseCallCounter := uint32(0)
bt := timer.NewBlockTimer(timer.StaticBlockMeter(blockDur), func() {
baseCallCounter++
})
require.NoError(t, bt.Reset())
intervalNum := uint32(7)
tickN(bt, intervalNum*blockDur)
require.Equal(t, intervalNum, uint32(baseCallCounter))
}
func TestNewOneTickTimer(t *testing.T) {
blockDur := uint32(1)
baseCallCounter := 0
bt := timer.NewOneTickTimer(timer.StaticBlockMeter(blockDur), func() {
baseCallCounter++
})
require.NoError(t, bt.Reset())
tickN(bt, 10)
require.Equal(t, 1, baseCallCounter) // happens once no matter what
t.Run("zero duration", func(t *testing.T) {
blockDur = uint32(0)
baseCallCounter = 0
bt = timer.NewOneTickTimer(timer.StaticBlockMeter(blockDur), func() {
baseCallCounter++
})
require.NoError(t, bt.Reset())
tickN(bt, 10)
require.Equal(t, 1, baseCallCounter)
})
}
func TestBlockTimer_TickSameHeight(t *testing.T) {
var baseCounter int
blockDur := uint32(2)
bt := timer.NewBlockTimer(
func() (uint32, error) { return blockDur, nil },
func() { baseCounter++ })
require.NoError(t, bt.Reset())
check := func(t *testing.T, h uint32, base int) {
for range 2 * int(blockDur) {
bt.Tick(h)
require.Equal(t, base, baseCounter)
}
}
check(t, 1, 0)
check(t, 2, 1)
check(t, 3, 1)
check(t, 4, 2)
t.Run("works the same way after `Reset()`", func(t *testing.T) {
t.Run("same block duration", func(t *testing.T) {
require.NoError(t, bt.Reset())
baseCounter = 0
check(t, 1, 0)
check(t, 2, 1)
check(t, 3, 1)
check(t, 4, 2)
})
t.Run("different block duration", func(t *testing.T) {
blockDur = 3
require.NoError(t, bt.Reset())
baseCounter = 0
check(t, 1, 0)
check(t, 2, 0)
check(t, 3, 1)
check(t, 4, 1)
check(t, 5, 1)
check(t, 6, 2)
})
})
}