[#1445] engine/test: Add test for GC handling of expired tombstones
Since the GC behavior is changing drastically. This test is needed to ensure that the GC correctly deletes expired tombstones and graves. The test uses graves of both old and new formats. Signed-off-by: Aleksey Savchuk <a.savchuk@yadro.com>
This commit is contained in:
parent
e119f35827
commit
cee94aae33
1 changed files with 111 additions and 0 deletions
111
pkg/local_object_storage/engine/gc_test.go
Normal file
111
pkg/local_object_storage/engine/gc_test.go
Normal file
|
@ -0,0 +1,111 @@
|
|||
package engine
|
||||
|
||||
import (
|
||||
"context"
|
||||
"strconv"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
objectCore "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/core/object"
|
||||
"git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/internal/testutil"
|
||||
meta "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/metabase"
|
||||
"git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/shard"
|
||||
"git.frostfs.info/TrueCloudLab/frostfs-node/pkg/util"
|
||||
objectV2 "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/object"
|
||||
"git.frostfs.info/TrueCloudLab/frostfs-sdk-go/client"
|
||||
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"
|
||||
"github.com/panjf2000/ants/v2"
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
||||
func testPopulateWithObjects(t testing.TB, engine *StorageEngine, cnt cid.ID, objectCount int) (objects []*objectSDK.Object) {
|
||||
require.Positive(t, objectCount)
|
||||
|
||||
var putPrm PutPrm
|
||||
for range objectCount {
|
||||
putPrm.Object = testutil.GenerateObjectWithCID(cnt)
|
||||
require.NoError(t, engine.Put(context.Background(), putPrm))
|
||||
objects = append(objects, putPrm.Object)
|
||||
}
|
||||
return objects
|
||||
}
|
||||
|
||||
func testInhumeObjects(t testing.TB, engine *StorageEngine, objects []*objectSDK.Object, expEpoch uint64) (tombstone *objectSDK.Object) {
|
||||
require.NotEmpty(t, objects)
|
||||
cnt := objectCore.AddressOf(objects[0]).Container()
|
||||
|
||||
tombstone = testutil.GenerateObjectWithCID(cnt)
|
||||
tombstone.SetType(objectSDK.TypeTombstone)
|
||||
testutil.AddAttribute(tombstone, objectV2.SysAttributeExpEpoch, strconv.FormatUint(expEpoch, 10))
|
||||
|
||||
var putPrm PutPrm
|
||||
putPrm.Object = tombstone
|
||||
require.NoError(t, engine.Put(context.Background(), putPrm))
|
||||
|
||||
var addrs []oid.Address
|
||||
for _, object := range objects {
|
||||
addrs = append(addrs, objectCore.AddressOf(object))
|
||||
}
|
||||
tombstoneAddr := objectCore.AddressOf(tombstone)
|
||||
|
||||
pivot := len(objects) / 2
|
||||
|
||||
var inhumePrm InhumePrm
|
||||
inhumePrm.WithTarget(tombstoneAddr, expEpoch, addrs[:pivot]...)
|
||||
err := engine.Inhume(context.Background(), inhumePrm)
|
||||
require.NoError(t, err)
|
||||
|
||||
inhumePrm.WithTarget(tombstoneAddr, meta.NoExpirationEpoch, addrs[pivot:]...)
|
||||
err = engine.Inhume(context.Background(), inhumePrm)
|
||||
require.NoError(t, err)
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
func TestGCHandleExpiredTombstones(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
const (
|
||||
numShards = 2
|
||||
objectCount = 10 * numShards
|
||||
expEpoch = 1
|
||||
)
|
||||
|
||||
container := cidtest.ID()
|
||||
|
||||
engine := testNewEngine(t).
|
||||
setShardsNumAdditionalOpts(t, numShards, func(_ int) []shard.Option {
|
||||
return []shard.Option{
|
||||
shard.WithGCWorkerPoolInitializer(func(sz int) util.WorkerPool {
|
||||
pool, err := ants.NewPool(sz)
|
||||
require.NoError(t, err)
|
||||
return pool
|
||||
}),
|
||||
shard.WithTombstoneSource(tss{expEpoch}),
|
||||
}
|
||||
}).prepare(t).engine
|
||||
defer func() { require.NoError(t, engine.Close(context.Background())) }()
|
||||
|
||||
objects := testPopulateWithObjects(t, engine, container, objectCount)
|
||||
tombstone := testInhumeObjects(t, engine, objects, expEpoch)
|
||||
|
||||
engine.HandleNewEpoch(context.Background(), expEpoch+1)
|
||||
|
||||
var headPrm HeadPrm
|
||||
require.Eventually(t, func() bool {
|
||||
for _, object := range objects {
|
||||
headPrm.WithAddress(objectCore.AddressOf(object))
|
||||
_, err := engine.Head(context.Background(), headPrm)
|
||||
if !client.IsErrObjectNotFound(err) {
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
headPrm.WithAddress(objectCore.AddressOf(tombstone))
|
||||
_, err := engine.Head(context.Background(), headPrm)
|
||||
return client.IsErrObjectNotFound(err)
|
||||
}, 10*time.Second, 1*time.Second)
|
||||
}
|
Loading…
Add table
Reference in a new issue