package erasurecode_test import ( "testing" objectSDK "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object" "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object/erasurecode" oidtest "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object/id/test" "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) for _, part := range parts { require.NoError(t, objectSDK.CheckHeaderVerificationFields(part)) } }) 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) for _, part := range parts { require.NoError(t, objectSDK.CheckHeaderVerificationFields(part)) } }) 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()) } }) }