frostfs-node/pkg/innerring/processors/container/handlers_test.go

330 lines
8.4 KiB
Go
Raw Normal View History

package container
import (
"crypto/ecdsa"
"encoding/hex"
"fmt"
"testing"
"time"
frostfsidclient "git.frostfs.info/TrueCloudLab/frostfs-contract/frostfsid/client"
containercore "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/core/container"
cntClient "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/morph/client/container"
containerEvent "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/morph/event/container"
"git.frostfs.info/TrueCloudLab/frostfs-node/pkg/util/logger/test"
apistatus "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/client/status"
containerSDK "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container"
"git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/acl"
cid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/id"
frostfscrypto "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/crypto"
frostfsecdsa "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/crypto/ecdsa"
"git.frostfs.info/TrueCloudLab/frostfs-sdk-go/eacl"
"git.frostfs.info/TrueCloudLab/frostfs-sdk-go/netmap"
"git.frostfs.info/TrueCloudLab/frostfs-sdk-go/user"
"git.frostfs.info/TrueCloudLab/frostfs-sdk-go/version"
"github.com/nspcc-dev/neo-go/pkg/core/transaction"
"github.com/nspcc-dev/neo-go/pkg/crypto/keys"
"github.com/nspcc-dev/neo-go/pkg/network/payload"
"github.com/nspcc-dev/neo-go/pkg/util"
"github.com/stretchr/testify/require"
)
func TestPutEvent(t *testing.T) {
t.Parallel()
nst := &testNetworkState{
homHashDisabled: true,
epoch: 100,
}
mc := &testMorphClient{}
proc, err := New(&Params{
Log: test.NewLogger(t, true),
PoolSize: 2,
AlphabetState: &testAlphabetState{isAlphabet: true},
NetworkState: nst,
ContainerClient: &testContainerClient{},
MorphClient: mc,
FrostFSIDClient: &testFrostFSIDClient{},
})
require.NoError(t, err, "failed to create processor")
p, err := keys.NewPrivateKey()
require.NoError(t, err)
var usr user.ID
user.IDFromKey(&usr, (ecdsa.PublicKey)(*p.PublicKey()))
var pp netmap.PlacementPolicy
pp.AddReplicas(netmap.ReplicaDescriptor{})
var cnr containerSDK.Container
cnr.Init()
cnr.SetOwner(usr)
cnr.SetPlacementPolicy(pp)
cnr.SetBasicACL(acl.Private)
containerSDK.DisableHomomorphicHashing(&cnr)
nr := &payload.P2PNotaryRequest{
MainTransaction: &transaction.Transaction{},
}
event := &testPutEvent{
cnr: &cnr,
pk: p,
st: nil,
nr: nr,
}
proc.handlePut(event)
for proc.pool.Running() > 0 {
time.Sleep(10 * time.Millisecond)
}
require.EqualValues(t, []*transaction.Transaction{nr.MainTransaction}, mc.transactions, "invalid notary requests")
}
func TestDeleteEvent(t *testing.T) {
t.Parallel()
nst := &testNetworkState{
homHashDisabled: true,
epoch: 100,
}
cc := &testContainerClient{
get: make(map[string]*containercore.Container),
}
p, err := keys.NewPrivateKey()
require.NoError(t, err)
mc := &testMorphClient{}
proc, err := New(&Params{
Log: test.NewLogger(t, true),
PoolSize: 2,
AlphabetState: &testAlphabetState{isAlphabet: true},
NetworkState: nst,
ContainerClient: cc,
MorphClient: mc,
FrostFSIDClient: &testFrostFSIDClient{},
})
require.NoError(t, err, "failed to create processor")
var usr user.ID
user.IDFromKey(&usr, (ecdsa.PublicKey)(*p.PublicKey()))
var pp netmap.PlacementPolicy
pp.AddReplicas(netmap.ReplicaDescriptor{})
var cnr containerSDK.Container
cnr.Init()
cnr.SetOwner(usr)
cnr.SetPlacementPolicy(pp)
cnr.SetBasicACL(acl.Private)
containerSDK.DisableHomomorphicHashing(&cnr)
var cid cid.ID
containerSDK.CalculateID(&cid, cnr)
cidBin := make([]byte, 32)
cid.Encode(cidBin)
nr := &payload.P2PNotaryRequest{
MainTransaction: &transaction.Transaction{},
}
ev := containerEvent.Delete{
ContainerIDValue: cidBin,
SignatureValue: p.Sign(cidBin),
NotaryRequestValue: nr,
PublicKeyValue: p.PublicKey().Bytes(),
}
var signature frostfscrypto.Signature
signer := frostfsecdsa.Signer(p.PrivateKey)
require.NoError(t, signature.Calculate(signer, ev.ContainerID()), "failed to calculate signature")
cc.get[hex.EncodeToString(ev.ContainerID())] = &containercore.Container{
Value: cnr,
Signature: signature,
}
proc.handleDelete(ev)
for proc.pool.Running() > 0 {
time.Sleep(10 * time.Millisecond)
}
var expectedDelete cntClient.DeletePrm
expectedDelete.SetCID(ev.ContainerID())
expectedDelete.SetSignature(ev.Signature())
require.EqualValues(t, []*transaction.Transaction{nr.MainTransaction}, mc.transactions, "invalid notary requests")
}
func TestSetEACLEvent(t *testing.T) {
t.Parallel()
nst := &testNetworkState{
homHashDisabled: true,
epoch: 100,
}
cc := &testContainerClient{
get: make(map[string]*containercore.Container),
}
mc := &testMorphClient{}
proc, err := New(&Params{
Log: test.NewLogger(t, true),
PoolSize: 2,
AlphabetState: &testAlphabetState{isAlphabet: true},
NetworkState: nst,
ContainerClient: cc,
MorphClient: mc,
FrostFSIDClient: &testFrostFSIDClient{},
})
require.NoError(t, err, "failed to create processor")
p, err := keys.NewPrivateKey()
require.NoError(t, err)
var usr user.ID
user.IDFromKey(&usr, (ecdsa.PublicKey)(*p.PublicKey()))
var pp netmap.PlacementPolicy
pp.AddReplicas(netmap.ReplicaDescriptor{})
var cnr containerSDK.Container
cnr.Init()
cnr.SetOwner(usr)
cnr.SetPlacementPolicy(pp)
cnr.SetBasicACL(acl.PrivateExtended)
containerSDK.DisableHomomorphicHashing(&cnr)
var cid cid.ID
containerSDK.CalculateID(&cid, cnr)
cidBytes := make([]byte, 32)
cid.Encode(cidBytes)
var signature frostfscrypto.Signature
signer := frostfsecdsa.Signer(p.PrivateKey)
require.NoError(t, signature.Calculate(signer, cidBytes), "failed to calculate signature")
cc.get[hex.EncodeToString(cidBytes)] = &containercore.Container{
Value: cnr,
Signature: signature,
}
table := eacl.NewTable()
table.SetCID(cid)
table.SetVersion(version.Current())
r := &eacl.Record{}
r.AddObjectContainerIDFilter(eacl.MatchStringEqual, cid)
table.AddRecord(r)
nr := &payload.P2PNotaryRequest{
MainTransaction: &transaction.Transaction{},
}
event := containerEvent.SetEACL{
TableValue: table.ToV2().StableMarshal(nil),
PublicKeyValue: p.PublicKey().Bytes(),
SignatureValue: p.Sign(table.ToV2().StableMarshal(nil)),
NotaryRequestValue: nr,
}
proc.handleSetEACL(event)
for proc.pool.Running() > 0 {
time.Sleep(10 * time.Millisecond)
}
var expectedPutEACL cntClient.PutEACLPrm
expectedPutEACL.SetTable(table.ToV2().StableMarshal(nil))
expectedPutEACL.SetKey(p.PublicKey().Bytes())
expectedPutEACL.SetSignature(p.Sign(table.ToV2().StableMarshal(nil)))
require.EqualValues(t, []*transaction.Transaction{nr.MainTransaction}, mc.transactions, "invalid notary requests")
}
type testAlphabetState struct {
isAlphabet bool
}
func (s *testAlphabetState) IsAlphabet() bool {
return s.isAlphabet
}
type testNetworkState struct {
homHashDisabled bool
epoch uint64
}
func (s *testNetworkState) HomomorphicHashDisabled() (bool, error) {
return s.homHashDisabled, nil
}
func (s *testNetworkState) Epoch() (uint64, error) {
return s.epoch, nil
}
type testContainerClient struct {
contractAddress util.Uint160
get map[string]*containercore.Container
}
func (c *testContainerClient) ContractAddress() util.Uint160 {
return c.contractAddress
}
func (c *testContainerClient) Get(cid []byte) (*containercore.Container, error) {
key := hex.EncodeToString(cid)
if cont, found := c.get[key]; found {
return cont, nil
}
return nil, new(apistatus.ContainerNotFound)
}
var _ putEvent = &testPutEvent{}
type testPutEvent struct {
cnr *containerSDK.Container
pk *keys.PrivateKey
st []byte
nr *payload.P2PNotaryRequest
}
func (e *testPutEvent) MorphEvent() {}
func (e *testPutEvent) Container() []byte {
return e.cnr.Marshal()
}
func (e *testPutEvent) PublicKey() []byte {
return e.pk.PublicKey().Bytes()
}
func (e *testPutEvent) Signature() []byte {
return e.pk.Sign(e.cnr.Marshal())
}
func (e *testPutEvent) SessionToken() []byte {
return e.st
}
func (e *testPutEvent) NotaryRequest() *payload.P2PNotaryRequest {
return e.nr
}
type testMorphClient struct {
transactions []*transaction.Transaction
}
func (c *testMorphClient) NotarySignAndInvokeTX(mainTx *transaction.Transaction) error {
c.transactions = append(c.transactions, mainTx)
return nil
}
type testFrostFSIDClient struct{}
func (c *testFrostFSIDClient) GetSubject(addr util.Uint160) (*frostfsidclient.Subject, error) {
return nil, fmt.Errorf("subject not found")
}