forked from TrueCloudLab/frostfs-node
221 lines
6.4 KiB
Go
221 lines
6.4 KiB
Go
package engine
|
|
|
|
import (
|
|
"context"
|
|
"testing"
|
|
|
|
"git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/internal/testutil"
|
|
"git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/shard"
|
|
"git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/shard/mode"
|
|
"git.frostfs.info/TrueCloudLab/frostfs-node/pkg/util/logger/test"
|
|
cid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/id"
|
|
cidtest "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/id/test"
|
|
objectSDK "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object"
|
|
oid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object/id"
|
|
oidtest "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object/id/test"
|
|
"github.com/stretchr/testify/require"
|
|
)
|
|
|
|
func TestContainerList(t *testing.T) {
|
|
t.Parallel()
|
|
|
|
s1 := testNewShard(t)
|
|
s2 := testNewShard(t)
|
|
s3 := testNewShard(t)
|
|
|
|
e := testNewEngine(t).setInitializedShards(t, s1, s2, s3).engine
|
|
e.log = test.NewLogger(t)
|
|
defer e.Close(context.Background())
|
|
|
|
const containerCount = 10
|
|
expStat := testPutComplexObject(t, []*shard.Shard{s1, s2, s3}, containerCount, nil)
|
|
expStat = testPutSimpleObject(t, []*shard.Shard{s1, s2, s3}, containerCount, expStat)
|
|
expStat = testPutSimpleObject(t, []*shard.Shard{s1, s2}, containerCount, expStat)
|
|
expStat = testPutSimpleObject(t, []*shard.Shard{s2, s3}, containerCount, expStat)
|
|
expStat = testPutSimpleObject(t, []*shard.Shard{s1}, containerCount, expStat)
|
|
expStat = testPutSimpleObject(t, []*shard.Shard{s2}, containerCount, expStat)
|
|
expStat = testPutSimpleObject(t, []*shard.Shard{s3}, containerCount, expStat)
|
|
|
|
t.Run("with default limit", func(t *testing.T) {
|
|
var prm ContainerStatPrm
|
|
prm.Limit = 10_000
|
|
res, err := e.ContainerStat(context.Background(), prm)
|
|
require.NoError(t, err)
|
|
require.NotNil(t, res)
|
|
require.ElementsMatch(t, expStat, res.ContainerStats)
|
|
require.False(t, res.Partial)
|
|
})
|
|
|
|
t.Run("with limit, batched", func(t *testing.T) {
|
|
var prm ContainerStatPrm
|
|
prm.Limit = 1
|
|
var stats []ContainerStat
|
|
|
|
for {
|
|
res, err := e.ContainerStat(context.Background(), prm)
|
|
require.NoError(t, err)
|
|
require.NotNil(t, res)
|
|
require.False(t, res.Partial)
|
|
if len(res.ContainerStats) == 0 {
|
|
break
|
|
}
|
|
stats = append(stats, res.ContainerStats...)
|
|
last := res.ContainerStats[len(res.ContainerStats)-1].ContainerID
|
|
prm.StartFromContainerID = &last
|
|
prm.Limit += 1
|
|
}
|
|
|
|
require.ElementsMatch(t, expStat, stats)
|
|
})
|
|
|
|
t.Run("by container id", func(t *testing.T) {
|
|
for _, cc := range []int{1, 2, 3, 4, 5} {
|
|
var prm ContainerStatPrm
|
|
for idx := 0; idx+cc < len(expStat); idx += cc {
|
|
prm.ContainerID = nil
|
|
for i := 0; i < cc; i++ {
|
|
prm.ContainerID = append(prm.ContainerID, expStat[idx+i].ContainerID)
|
|
}
|
|
prm.Limit = uint32(len(prm.ContainerID))
|
|
res, err := e.ContainerStat(context.Background(), prm)
|
|
require.NoError(t, err)
|
|
require.NotNil(t, res)
|
|
require.False(t, res.Partial)
|
|
require.ElementsMatch(t, expStat[idx:idx+cc], res.ContainerStats)
|
|
}
|
|
}
|
|
})
|
|
|
|
t.Run("unknown container id", func(t *testing.T) {
|
|
var prm ContainerStatPrm
|
|
prm.ContainerID = append(prm.ContainerID, cidtest.ID())
|
|
prm.Limit = uint32(len(prm.ContainerID))
|
|
res, err := e.ContainerStat(context.Background(), prm)
|
|
require.NoError(t, err)
|
|
require.NotNil(t, res)
|
|
require.False(t, res.Partial)
|
|
require.ElementsMatch(t, []ContainerStat{{ContainerID: prm.ContainerID[0]}}, res.ContainerStats)
|
|
})
|
|
|
|
t.Run("degraded shard", func(t *testing.T) {
|
|
s1.SetMode(mode.Degraded)
|
|
var prm ContainerStatPrm
|
|
prm.Limit = 10_000
|
|
res, err := e.ContainerStat(context.Background(), prm)
|
|
require.NoError(t, err)
|
|
require.NotNil(t, res)
|
|
require.True(t, res.Partial)
|
|
})
|
|
}
|
|
|
|
func testPutComplexObject(t *testing.T, shards []*shard.Shard, count int, stats []ContainerStat) []ContainerStat {
|
|
const payloadSize = 10 * 1024
|
|
for count > 0 {
|
|
var cnr cid.ID
|
|
var stat *ContainerStat
|
|
var newStat bool
|
|
if len(stats) == 0 || count%2 == 0 {
|
|
cnr = cidtest.ID()
|
|
stat = &ContainerStat{ContainerID: cnr}
|
|
newStat = true
|
|
} else {
|
|
cnr = stats[count%len(stats)].ContainerID
|
|
stat = &stats[count%len(stats)]
|
|
}
|
|
|
|
parentID := oidtest.ID()
|
|
splitID := objectSDK.NewSplitID()
|
|
|
|
parent := testutil.GenerateObjectWithCID(cnr)
|
|
parent.SetID(parentID)
|
|
parent.SetPayload(nil)
|
|
|
|
const childCount = 10
|
|
children := make([]*objectSDK.Object, childCount)
|
|
childIDs := make([]oid.ID, childCount)
|
|
for i := range children {
|
|
children[i] = testutil.GenerateObjectWithCID(cnr)
|
|
if i != 0 {
|
|
children[i].SetPreviousID(childIDs[i-1])
|
|
}
|
|
if i == len(children)-1 {
|
|
children[i].SetParent(parent)
|
|
}
|
|
children[i].SetSplitID(splitID)
|
|
children[i].SetPayload(make([]byte, payloadSize))
|
|
children[i].SetPayloadSize(payloadSize)
|
|
childIDs[i], _ = children[i].ID()
|
|
|
|
stat.SizeLogic += payloadSize
|
|
stat.CountLogic += 1
|
|
stat.CountPhy += 1
|
|
}
|
|
stat.CountUser += 1
|
|
|
|
link := testutil.GenerateObjectWithCID(cnr)
|
|
link.SetParent(parent)
|
|
link.SetParentID(parentID)
|
|
link.SetSplitID(splitID)
|
|
link.SetChildren(childIDs...)
|
|
|
|
stat.CountLogic += 1
|
|
stat.CountPhy += 1
|
|
stat.SizeLogic += link.PayloadSize()
|
|
|
|
for i := range children {
|
|
sh := shards[i%len(shards)]
|
|
var putPrm shard.PutPrm
|
|
putPrm.SetObject(children[i])
|
|
_, err := sh.Put(context.Background(), putPrm)
|
|
require.NoError(t, err)
|
|
}
|
|
sh := shards[count%len(shards)]
|
|
var putPrm shard.PutPrm
|
|
putPrm.SetObject(link)
|
|
_, err := sh.Put(context.Background(), putPrm)
|
|
require.NoError(t, err)
|
|
|
|
if newStat {
|
|
stats = append(stats, *stat)
|
|
}
|
|
count--
|
|
}
|
|
return stats
|
|
}
|
|
|
|
func testPutSimpleObject(t *testing.T, shards []*shard.Shard, count int, stats []ContainerStat) []ContainerStat {
|
|
const payloadSize = 7 * 1024
|
|
for count > 0 {
|
|
var cnr cid.ID
|
|
var stat *ContainerStat
|
|
var newStat bool
|
|
if len(stats) == 0 || count%2 == 0 {
|
|
cnr = cidtest.ID()
|
|
stat = &ContainerStat{ContainerID: cnr}
|
|
newStat = true
|
|
} else {
|
|
cnr = stats[count%len(stats)].ContainerID
|
|
stat = &stats[count%len(stats)]
|
|
}
|
|
|
|
obj := testutil.GenerateObjectWithCID(cnr)
|
|
obj.SetPayload(make([]byte, payloadSize))
|
|
obj.SetPayloadSize(payloadSize)
|
|
stat.SizeLogic += payloadSize
|
|
stat.CountLogic += 1
|
|
stat.CountPhy += 1
|
|
stat.CountUser += 1
|
|
|
|
sh := shards[count%len(shards)]
|
|
var putPrm shard.PutPrm
|
|
putPrm.SetObject(obj)
|
|
_, err := sh.Put(context.Background(), putPrm)
|
|
require.NoError(t, err)
|
|
|
|
if newStat {
|
|
stats = append(stats, *stat)
|
|
}
|
|
count--
|
|
}
|
|
return stats
|
|
}
|