[#224] netmap: Add tests for NewEpoch
Ensure snapshots are handled properly. Signed-off-by: Evgenii Stratonikov <evgeniy@nspcc.ru>
This commit is contained in:
parent
9884f8e68f
commit
666e1d6d8d
2 changed files with 93 additions and 6 deletions
|
@ -52,8 +52,8 @@ const (
|
||||||
const (
|
const (
|
||||||
// V2 format
|
// V2 format
|
||||||
_ nodeState = iota
|
_ nodeState = iota
|
||||||
onlineState
|
OnlineState
|
||||||
offlineState
|
OfflineState
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
|
@ -323,7 +323,7 @@ func UpdateState(state int, publicKey interop.PublicKey) {
|
||||||
}
|
}
|
||||||
|
|
||||||
switch nodeState(state) {
|
switch nodeState(state) {
|
||||||
case offlineState:
|
case OfflineState:
|
||||||
removeFromNetmap(ctx, publicKey)
|
removeFromNetmap(ctx, publicKey)
|
||||||
runtime.Log("remove storage node from the network map")
|
runtime.Log("remove storage node from the network map")
|
||||||
default:
|
default:
|
||||||
|
@ -343,7 +343,7 @@ func UpdateStateIR(state nodeState, publicKey interop.PublicKey) {
|
||||||
common.CheckAlphabetWitness(common.AlphabetAddress())
|
common.CheckAlphabetWitness(common.AlphabetAddress())
|
||||||
|
|
||||||
switch state {
|
switch state {
|
||||||
case offlineState:
|
case OfflineState:
|
||||||
removeFromNetmap(ctx, publicKey)
|
removeFromNetmap(ctx, publicKey)
|
||||||
default:
|
default:
|
||||||
panic("unsupported state")
|
panic("unsupported state")
|
||||||
|
@ -396,7 +396,7 @@ func NewEpoch(epochNum int) {
|
||||||
panic("invalid epoch") // ignore invocations with invalid epoch
|
panic("invalid epoch") // ignore invocations with invalid epoch
|
||||||
}
|
}
|
||||||
|
|
||||||
dataOnlineState := filterNetmap(ctx, onlineState)
|
dataOnlineState := filterNetmap(ctx, OnlineState)
|
||||||
|
|
||||||
runtime.Log("process new epoch")
|
runtime.Log("process new epoch")
|
||||||
|
|
||||||
|
@ -556,7 +556,7 @@ func addToNetmap(ctx storage.Context, n storageNode) {
|
||||||
|
|
||||||
node = netmapNode{
|
node = netmapNode{
|
||||||
node: n,
|
node: n,
|
||||||
state: onlineState,
|
state: OnlineState,
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
|
@ -4,6 +4,7 @@ import (
|
||||||
"math/big"
|
"math/big"
|
||||||
"math/rand"
|
"math/rand"
|
||||||
"path"
|
"path"
|
||||||
|
"strings"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/nspcc-dev/neo-go/pkg/encoding/bigint"
|
"github.com/nspcc-dev/neo-go/pkg/encoding/bigint"
|
||||||
|
@ -13,6 +14,7 @@ import (
|
||||||
"github.com/nspcc-dev/neo-go/pkg/vm/stackitem"
|
"github.com/nspcc-dev/neo-go/pkg/vm/stackitem"
|
||||||
"github.com/nspcc-dev/neofs-contract/common"
|
"github.com/nspcc-dev/neofs-contract/common"
|
||||||
"github.com/nspcc-dev/neofs-contract/container"
|
"github.com/nspcc-dev/neofs-contract/container"
|
||||||
|
"github.com/nspcc-dev/neofs-contract/netmap"
|
||||||
"github.com/stretchr/testify/require"
|
"github.com/stretchr/testify/require"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -104,6 +106,91 @@ func TestAddPeer(t *testing.T) {
|
||||||
c.Invoke(t, stackitem.Null{}, "addPeerIR", dummyInfo.raw)
|
c.Invoke(t, stackitem.Null{}, "addPeerIR", dummyInfo.raw)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestNewEpoch(t *testing.T) {
|
||||||
|
rand.Seed(42)
|
||||||
|
|
||||||
|
const epochCount = netmap.SnapshotCount * 2
|
||||||
|
|
||||||
|
cNm := newNetmapInvoker(t)
|
||||||
|
nodes := make([][]testNodeInfo, epochCount)
|
||||||
|
for i := range nodes {
|
||||||
|
size := rand.Int()%5 + 1
|
||||||
|
arr := make([]testNodeInfo, size)
|
||||||
|
for j := 0; j < size; j++ {
|
||||||
|
arr[j] = newStorageNode(t, cNm)
|
||||||
|
}
|
||||||
|
nodes[i] = arr
|
||||||
|
}
|
||||||
|
|
||||||
|
for i := 0; i < epochCount; i++ {
|
||||||
|
for _, tn := range nodes[i] {
|
||||||
|
cNm.WithSigners(tn.signer).Invoke(t, stackitem.Null{}, "addPeer", tn.raw)
|
||||||
|
cNm.Invoke(t, stackitem.Null{}, "addPeerIR", tn.raw)
|
||||||
|
}
|
||||||
|
|
||||||
|
if i > 0 {
|
||||||
|
// Remove random nodes from the previous netmap.
|
||||||
|
current := make([]testNodeInfo, 0, len(nodes[i])+len(nodes[i-1]))
|
||||||
|
current = append(current, nodes[i]...)
|
||||||
|
|
||||||
|
for j := range nodes[i-1] {
|
||||||
|
if rand.Int()%3 == 0 {
|
||||||
|
cNm.Invoke(t, stackitem.Null{}, "updateStateIR",
|
||||||
|
int64(netmap.OfflineState), nodes[i-1][j].pub)
|
||||||
|
} else {
|
||||||
|
current = append(current, nodes[i-1][j])
|
||||||
|
}
|
||||||
|
}
|
||||||
|
nodes[i] = current
|
||||||
|
}
|
||||||
|
cNm.Invoke(t, stackitem.Null{}, "newEpoch", i+1)
|
||||||
|
|
||||||
|
t.Logf("Epoch: %d, Netmap()", i)
|
||||||
|
s, err := cNm.TestInvoke(t, "netmap")
|
||||||
|
require.NoError(t, err)
|
||||||
|
require.Equal(t, 1, s.Len())
|
||||||
|
checkSnapshot(t, s, nodes[i])
|
||||||
|
|
||||||
|
for j := 0; j <= i && j < netmap.SnapshotCount; j++ {
|
||||||
|
t.Logf("Epoch: %d, diff: %d", i, j)
|
||||||
|
s, err := cNm.TestInvoke(t, "snapshot", int64(j))
|
||||||
|
require.NoError(t, err)
|
||||||
|
require.Equal(t, 1, s.Len())
|
||||||
|
checkSnapshot(t, s, nodes[i-j])
|
||||||
|
}
|
||||||
|
|
||||||
|
_, err = cNm.TestInvoke(t, "snapshot", netmap.SnapshotCount)
|
||||||
|
require.Error(t, err)
|
||||||
|
require.True(t, strings.Contains(err.Error(), "incorrect diff"))
|
||||||
|
|
||||||
|
_, err = cNm.TestInvoke(t, "snapshot", -1)
|
||||||
|
require.Error(t, err)
|
||||||
|
require.True(t, strings.Contains(err.Error(), "incorrect diff"))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func checkSnapshot(t *testing.T, s *vm.Stack, nodes []testNodeInfo) {
|
||||||
|
arr, ok := s.Pop().Value().([]stackitem.Item)
|
||||||
|
require.True(t, ok, "expected array")
|
||||||
|
require.Equal(t, len(nodes), len(arr), "expected %d nodes", len(nodes))
|
||||||
|
|
||||||
|
actual := make([][]byte, len(nodes))
|
||||||
|
expected := make([][]byte, len(nodes))
|
||||||
|
for i := range nodes {
|
||||||
|
n, ok := arr[i].Value().([]stackitem.Item)
|
||||||
|
require.True(t, ok, "expected node struct")
|
||||||
|
require.Equal(t, 1, len(n), "expected single field")
|
||||||
|
|
||||||
|
raw, ok := n[0].Value().([]byte)
|
||||||
|
require.True(t, ok, "expected bytes")
|
||||||
|
|
||||||
|
actual[i] = raw
|
||||||
|
expected[i] = nodes[i].raw
|
||||||
|
}
|
||||||
|
|
||||||
|
require.ElementsMatch(t, expected, actual, "snapshot is different")
|
||||||
|
}
|
||||||
|
|
||||||
func TestUpdateState(t *testing.T) {
|
func TestUpdateState(t *testing.T) {
|
||||||
cNm := newNetmapInvoker(t)
|
cNm := newNetmapInvoker(t)
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue