[#280] ir: Add governance processor unit tests

Signed-off-by: Dmitrii Stepanov <d.stepanov@yadro.com>
This commit is contained in:
Dmitrii Stepanov 2023-04-27 11:25:17 +03:00 committed by Evgenii Stratonikov
parent 31b4da225a
commit fb5dcc15d2
2 changed files with 331 additions and 8 deletions

View file

@ -0,0 +1,304 @@
package governance
import (
"encoding/binary"
"sort"
"testing"
"time"
"git.frostfs.info/TrueCloudLab/frostfs-node/pkg/morph/client"
frostfscontract "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/morph/client/frostfs"
nmClient "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/morph/client/netmap"
"git.frostfs.info/TrueCloudLab/frostfs-node/pkg/morph/event/rolemanagement"
"git.frostfs.info/TrueCloudLab/frostfs-node/pkg/util/logger/test"
"github.com/nspcc-dev/neo-go/pkg/core/native/noderoles"
"github.com/nspcc-dev/neo-go/pkg/crypto/keys"
"github.com/nspcc-dev/neo-go/pkg/util"
"github.com/stretchr/testify/require"
)
func TestHandleAlphabetSyncEvent(t *testing.T) {
t.Parallel()
testKeys := generateTestKeys(t)
es := &testEpochState{
epoch: 100,
}
as := &testAlphabetState{
isAlphabet: true,
}
v := &testVoter{}
irf := &testIRFetcher{
publicKeys: testKeys.sidechainKeys,
}
m := &testMorphClient{
commiteeKeys: testKeys.sidechainKeys,
}
mn := &testMainnetClient{
alphabetKeys: testKeys.mainnetKeys,
}
f := &testFrostFSClient{}
nm := &testNetmapClient{}
proc, err := New(
&Params{
Log: test.NewLogger(t, true),
EpochState: es,
AlphabetState: as,
Voter: v,
IRFetcher: irf,
NotaryDisabled: true,
MorphClient: m,
MainnetClient: mn,
FrostFSClient: f,
NetmapClient: nm,
},
)
require.NoError(t, err, "failed to create processor")
ev := Sync{
txHash: util.Uint256{100},
}
proc.HandleAlphabetSync(ev)
for proc.pool.Running() > 0 {
time.Sleep(10 * time.Millisecond)
}
require.EqualValues(t, []VoteValidatorPrm{
{
Validators: testKeys.newAlphabetExp,
Hash: &ev.txHash,
},
}, v.votes, "invalid vote calls")
var irUpdateExp nmClient.UpdateIRPrm
irUpdateExp.SetKeys(testKeys.newInnerRingExp)
irUpdateExp.SetHash(ev.txHash)
require.EqualValues(t, []nmClient.UpdateIRPrm{irUpdateExp}, nm.updates, "invalid IR updates")
var expAlphabetUpdates []client.UpdateAlphabetListPrm
require.EqualValues(t, expAlphabetUpdates, m.alphabetUpdates, "invalid alphabet updates")
var expNotaryUpdates []client.UpdateNotaryListPrm
require.EqualValues(t, expNotaryUpdates, m.notaryUpdates, "invalid notary list updates")
buf := make([]byte, 8)
binary.LittleEndian.PutUint64(buf, es.epoch)
id := append([]byte(alphabetUpdateIDPrefix), buf...)
var expFrostFSAlphabetUpd frostfscontract.AlphabetUpdatePrm
expFrostFSAlphabetUpd.SetID(id)
expFrostFSAlphabetUpd.SetPubs(testKeys.newAlphabetExp)
require.EqualValues(t, []frostfscontract.AlphabetUpdatePrm{expFrostFSAlphabetUpd}, f.updates, "invalid FrostFS alphabet updates")
}
func TestHandleAlphabetDesignateEvent(t *testing.T) {
t.Parallel()
testKeys := generateTestKeys(t)
es := &testEpochState{
epoch: 100,
}
as := &testAlphabetState{
isAlphabet: true,
}
v := &testVoter{}
irf := &testIRFetcher{
publicKeys: testKeys.sidechainKeys,
}
m := &testMorphClient{
commiteeKeys: testKeys.sidechainKeys,
}
mn := &testMainnetClient{
alphabetKeys: testKeys.mainnetKeys,
}
f := &testFrostFSClient{}
nm := &testNetmapClient{}
proc, err := New(
&Params{
Log: test.NewLogger(t, true),
EpochState: es,
AlphabetState: as,
Voter: v,
IRFetcher: irf,
NotaryDisabled: false,
MorphClient: m,
MainnetClient: mn,
FrostFSClient: f,
NetmapClient: nm,
},
)
require.NoError(t, err, "failed to create processor")
ev := rolemanagement.Designate{
TxHash: util.Uint256{100},
Role: noderoles.NeoFSAlphabet,
}
proc.HandleAlphabetSync(ev)
for proc.pool.Running() > 0 {
time.Sleep(10 * time.Millisecond)
}
require.EqualValues(t, []VoteValidatorPrm{
{
Validators: testKeys.newAlphabetExp,
Hash: &ev.TxHash,
},
}, v.votes, "invalid vote calls")
var irUpdatesExp []nmClient.UpdateIRPrm
require.EqualValues(t, irUpdatesExp, nm.updates, "invalid IR updates")
var alpabetUpdExp client.UpdateAlphabetListPrm
alpabetUpdExp.SetList(testKeys.newInnerRingExp)
alpabetUpdExp.SetHash(ev.TxHash)
require.EqualValues(t, []client.UpdateAlphabetListPrm{alpabetUpdExp}, m.alphabetUpdates, "invalid alphabet updates")
var expNotaryUpdate client.UpdateNotaryListPrm
expNotaryUpdate.SetList(testKeys.newAlphabetExp)
expNotaryUpdate.SetHash(ev.TxHash)
require.EqualValues(t, []client.UpdateNotaryListPrm{expNotaryUpdate}, m.notaryUpdates, "invalid notary list updates")
buf := make([]byte, 8)
binary.LittleEndian.PutUint64(buf, es.epoch)
id := append([]byte(alphabetUpdateIDPrefix), buf...)
var expFrostFSAlphabetUpd frostfscontract.AlphabetUpdatePrm
expFrostFSAlphabetUpd.SetID(id)
expFrostFSAlphabetUpd.SetPubs(testKeys.newAlphabetExp)
require.EqualValues(t, []frostfscontract.AlphabetUpdatePrm{expFrostFSAlphabetUpd}, f.updates, "invalid FrostFS alphabet updates")
}
type testKeys struct {
sidechainKeys keys.PublicKeys
mainnetKeys keys.PublicKeys
newAlphabetExp keys.PublicKeys
newInnerRingExp keys.PublicKeys
}
func generateTestKeys(t *testing.T) testKeys {
for {
var result testKeys
for i := 0; i < 4; i++ {
pk, err := keys.NewPrivateKey()
require.NoError(t, err, "failed to create private key")
result.sidechainKeys = append(result.sidechainKeys, pk.PublicKey())
}
result.mainnetKeys = append(result.mainnetKeys, result.sidechainKeys...)
pk, err := keys.NewPrivateKey()
require.NoError(t, err, "failed to create private key")
result.mainnetKeys = append(result.mainnetKeys, pk.PublicKey())
result.newAlphabetExp, err = newAlphabetList(result.sidechainKeys, result.mainnetKeys)
require.NoError(t, err, "failed to create expected new alphabet")
if len(result.newAlphabetExp) == 0 {
continue //can be happen because of random and sort
}
var irKeys keys.PublicKeys
irKeys = append(irKeys, result.sidechainKeys...)
result.newInnerRingExp, err = updateInnerRing(irKeys, result.sidechainKeys, result.newAlphabetExp)
require.NoError(t, err, "failed to create expected new IR")
sort.Sort(result.newInnerRingExp)
return result
}
}
type testEpochState struct {
epoch uint64
}
func (s *testEpochState) EpochCounter() uint64 {
return s.epoch
}
type testAlphabetState struct {
isAlphabet bool
}
func (s *testAlphabetState) IsAlphabet() bool {
return s.isAlphabet
}
type testVoter struct {
votes []VoteValidatorPrm
}
func (v *testVoter) VoteForSidechainValidator(prm VoteValidatorPrm) error {
v.votes = append(v.votes, prm)
return nil
}
type testIRFetcher struct {
publicKeys keys.PublicKeys
}
func (f *testIRFetcher) InnerRingKeys() (keys.PublicKeys, error) {
return f.publicKeys, nil
}
type testMorphClient struct {
commiteeKeys keys.PublicKeys
alphabetUpdates []client.UpdateAlphabetListPrm
notaryUpdates []client.UpdateNotaryListPrm
}
func (c *testMorphClient) Committee() (res keys.PublicKeys, err error) {
return c.commiteeKeys, nil
}
func (c *testMorphClient) UpdateNeoFSAlphabetList(prm client.UpdateAlphabetListPrm) error {
c.alphabetUpdates = append(c.alphabetUpdates, prm)
return nil
}
func (c *testMorphClient) UpdateNotaryList(prm client.UpdateNotaryListPrm) error {
c.notaryUpdates = append(c.notaryUpdates, prm)
return nil
}
type testMainnetClient struct {
alphabetKeys keys.PublicKeys
designateHash util.Uint160
}
func (c *testMainnetClient) NeoFSAlphabetList() (res keys.PublicKeys, err error) {
return c.alphabetKeys, nil
}
func (c *testMainnetClient) GetDesignateHash() util.Uint160 {
return c.designateHash
}
type testFrostFSClient struct {
updates []frostfscontract.AlphabetUpdatePrm
}
func (c *testFrostFSClient) AlphabetUpdate(p frostfscontract.AlphabetUpdatePrm) error {
c.updates = append(c.updates, p)
return nil
}
type testNetmapClient struct {
updates []nmClient.UpdateIRPrm
}
func (c *testNetmapClient) UpdateInnerRing(p nmClient.UpdateIRPrm) error {
c.updates = append(c.updates, p)
return nil
}

View file

@ -53,20 +53,39 @@ type (
InnerRingKeys() (keys.PublicKeys, error) InnerRingKeys() (keys.PublicKeys, error)
} }
FrostFSClient interface {
AlphabetUpdate(p frostfscontract.AlphabetUpdatePrm) error
}
NetmapClient interface {
UpdateInnerRing(p nmClient.UpdateIRPrm) error
}
MainnetClient interface {
NeoFSAlphabetList() (res keys.PublicKeys, err error)
GetDesignateHash() util.Uint160
}
MorphClient interface {
Committee() (res keys.PublicKeys, err error)
UpdateNeoFSAlphabetList(prm client.UpdateAlphabetListPrm) error
UpdateNotaryList(prm client.UpdateNotaryListPrm) error
}
// Processor of events related to governance in the network. // Processor of events related to governance in the network.
Processor struct { Processor struct {
log *logger.Logger log *logger.Logger
pool *ants.Pool pool *ants.Pool
frostfsClient *frostfscontract.Client frostfsClient FrostFSClient
netmapClient *nmClient.Client netmapClient NetmapClient
alphabetState AlphabetState alphabetState AlphabetState
epochState EpochState epochState EpochState
voter Voter voter Voter
irFetcher IRFetcher irFetcher IRFetcher
mainnetClient *client.Client mainnetClient MainnetClient
morphClient *client.Client morphClient MorphClient
notaryDisabled bool notaryDisabled bool
@ -82,10 +101,10 @@ type (
Voter Voter Voter Voter
IRFetcher IRFetcher IRFetcher IRFetcher
MorphClient *client.Client MorphClient MorphClient
MainnetClient *client.Client MainnetClient MainnetClient
FrostFSClient *frostfscontract.Client FrostFSClient FrostFSClient
NetmapClient *nmClient.Client NetmapClient NetmapClient
NotaryDisabled bool NotaryDisabled bool
} }