2024-02-28 11:51:48 +00:00
|
|
|
package erasurecode_test
|
|
|
|
|
|
|
|
import (
|
|
|
|
"testing"
|
|
|
|
|
2024-03-28 15:53:34 +00:00
|
|
|
objectSDK "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object"
|
2024-02-28 11:51:48 +00:00
|
|
|
"git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object/erasurecode"
|
2024-05-17 12:16:28 +00:00
|
|
|
oidtest "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object/id/test"
|
2024-02-28 11:51:48 +00:00
|
|
|
"github.com/nspcc-dev/neo-go/pkg/crypto/keys"
|
|
|
|
"github.com/stretchr/testify/require"
|
|
|
|
)
|
|
|
|
|
|
|
|
// The library can behave differently for big shard counts.
|
|
|
|
// This test checks we support the maximum number of chunks we promise.
|
|
|
|
func TestSplitMaxShardCount(t *testing.T) {
|
|
|
|
pk, err := keys.NewPrivateKey()
|
|
|
|
require.NoError(t, err)
|
|
|
|
|
|
|
|
original := newObject(t, 1024, pk)
|
|
|
|
|
|
|
|
t.Run("only data", func(t *testing.T) {
|
|
|
|
c, err := erasurecode.NewConstructor(erasurecode.MaxShardCount, 0)
|
|
|
|
require.NoError(t, err)
|
|
|
|
|
|
|
|
parts, err := c.Split(original, &pk.PrivateKey)
|
|
|
|
require.NoError(t, err)
|
|
|
|
require.Len(t, parts, erasurecode.MaxShardCount)
|
2024-03-28 15:53:34 +00:00
|
|
|
|
|
|
|
for _, part := range parts {
|
|
|
|
require.NoError(t, objectSDK.CheckHeaderVerificationFields(part))
|
|
|
|
}
|
2024-02-28 11:51:48 +00:00
|
|
|
})
|
|
|
|
t.Run("data + parity", func(t *testing.T) {
|
|
|
|
c, err := erasurecode.NewConstructor(1, erasurecode.MaxShardCount-1)
|
|
|
|
require.NoError(t, err)
|
|
|
|
|
|
|
|
parts, err := c.Split(original, &pk.PrivateKey)
|
|
|
|
require.NoError(t, err)
|
|
|
|
require.Len(t, parts, erasurecode.MaxShardCount)
|
2024-03-28 15:53:34 +00:00
|
|
|
|
|
|
|
for _, part := range parts {
|
|
|
|
require.NoError(t, objectSDK.CheckHeaderVerificationFields(part))
|
|
|
|
}
|
2024-02-28 11:51:48 +00:00
|
|
|
})
|
2024-05-17 12:16:28 +00:00
|
|
|
t.Run("ec parents are children of last Split part", func(t *testing.T) {
|
|
|
|
c, err := erasurecode.NewConstructor(1, erasurecode.MaxShardCount-1)
|
|
|
|
require.NoError(t, err)
|
|
|
|
|
|
|
|
splitted1 := newObject(t, 1024, pk)
|
|
|
|
splitted2 := newObject(t, 1024, pk)
|
|
|
|
|
|
|
|
splittedId1, _ := splitted1.ID()
|
|
|
|
splittedId2, _ := splitted2.ID()
|
|
|
|
|
|
|
|
splitID := objectSDK.NewSplitID()
|
|
|
|
parent := objectSDK.New()
|
|
|
|
parent.SetID(oidtest.ID())
|
|
|
|
parent.SetChildren(splittedId1, splittedId2)
|
|
|
|
parent.SetSplitID(splitID)
|
|
|
|
|
|
|
|
splitted1.SetSplitID(splitID)
|
|
|
|
splitted1.SetParent(parent)
|
|
|
|
splitted2.SetSplitID(splitID)
|
|
|
|
splitted2.SetParent(parent)
|
|
|
|
|
|
|
|
parts1, err := c.Split(splitted1, &pk.PrivateKey)
|
|
|
|
require.NoError(t, err)
|
|
|
|
require.Len(t, parts1, erasurecode.MaxShardCount)
|
|
|
|
|
|
|
|
for _, part := range parts1 {
|
|
|
|
require.NoError(t, objectSDK.CheckHeaderVerificationFields(part))
|
|
|
|
|
|
|
|
require.NotNil(t, part.ECHeader().ParentSplitID())
|
|
|
|
require.Equal(t, *splitID, *part.ECHeader().ParentSplitID())
|
|
|
|
require.NotNil(t, part.ECHeader().ParentSplitParentID())
|
|
|
|
}
|
|
|
|
|
|
|
|
parts2, err := c.Split(splitted2, &pk.PrivateKey)
|
|
|
|
require.NoError(t, err)
|
|
|
|
require.Len(t, parts1, erasurecode.MaxShardCount)
|
|
|
|
|
|
|
|
for _, part := range parts2 {
|
|
|
|
require.NoError(t, objectSDK.CheckHeaderVerificationFields(part))
|
|
|
|
|
|
|
|
require.NotNil(t, part.ECHeader().ParentSplitID())
|
|
|
|
require.Equal(t, *splitID, *part.ECHeader().ParentSplitID())
|
|
|
|
require.NotNil(t, part.ECHeader().ParentSplitParentID())
|
|
|
|
}
|
|
|
|
|
|
|
|
})
|
|
|
|
t.Run("ec parents are children of non-last Split part", func(t *testing.T) {
|
|
|
|
c, err := erasurecode.NewConstructor(1, erasurecode.MaxShardCount-1)
|
|
|
|
require.NoError(t, err)
|
|
|
|
|
|
|
|
splitted1 := newObject(t, 1024, pk)
|
|
|
|
splitted2 := newObject(t, 1024, pk)
|
|
|
|
|
|
|
|
splittedId1, _ := splitted1.ID()
|
|
|
|
splittedId2, _ := splitted2.ID()
|
|
|
|
|
|
|
|
splitID := objectSDK.NewSplitID()
|
|
|
|
parent := objectSDK.New()
|
|
|
|
// Such parent has got no ID.
|
|
|
|
parent.SetChildren(splittedId1, splittedId2)
|
|
|
|
parent.SetSplitID(splitID)
|
|
|
|
|
|
|
|
splitted1.SetSplitID(splitID)
|
|
|
|
splitted1.SetParent(parent)
|
|
|
|
splitted2.SetSplitID(splitID)
|
|
|
|
splitted2.SetParent(parent)
|
|
|
|
|
|
|
|
parts1, err := c.Split(splitted1, &pk.PrivateKey)
|
|
|
|
require.NoError(t, err)
|
|
|
|
require.Len(t, parts1, erasurecode.MaxShardCount)
|
|
|
|
|
|
|
|
for _, part := range parts1 {
|
|
|
|
require.NoError(t, objectSDK.CheckHeaderVerificationFields(part))
|
|
|
|
|
|
|
|
require.NotNil(t, part.ECHeader().ParentSplitID())
|
|
|
|
require.Equal(t, *splitID, *part.ECHeader().ParentSplitID())
|
|
|
|
require.Nil(t, part.ECHeader().ParentSplitParentID())
|
|
|
|
}
|
|
|
|
|
|
|
|
parts2, err := c.Split(splitted2, &pk.PrivateKey)
|
|
|
|
require.NoError(t, err)
|
|
|
|
require.Len(t, parts1, erasurecode.MaxShardCount)
|
|
|
|
|
|
|
|
for _, part := range parts2 {
|
|
|
|
require.NoError(t, objectSDK.CheckHeaderVerificationFields(part))
|
|
|
|
|
|
|
|
require.NotNil(t, part.ECHeader().ParentSplitID())
|
|
|
|
require.Equal(t, *splitID, *part.ECHeader().ParentSplitID())
|
|
|
|
require.Nil(t, part.ECHeader().ParentSplitParentID())
|
|
|
|
}
|
|
|
|
|
|
|
|
})
|
2024-02-28 11:51:48 +00:00
|
|
|
|
|
|
|
}
|