[#1527] engine: Add tests for handling expired objects on inhume and lock
All checks were successful
Tests and linters / Run gofumpt (pull_request) Successful in 2m11s
DCO action / DCO (pull_request) Successful in 2m27s
Vulncheck / Vulncheck (pull_request) Successful in 2m38s
Pre-commit hooks / Pre-commit (pull_request) Successful in 3m3s
Build / Build Components (pull_request) Successful in 3m20s
Tests and linters / gopls check (pull_request) Successful in 3m27s
Tests and linters / Staticcheck (pull_request) Successful in 4m0s
Tests and linters / Lint (pull_request) Successful in 4m39s
Tests and linters / Tests (pull_request) Successful in 5m9s
Tests and linters / Tests with -race (pull_request) Successful in 6m33s
Tests and linters / Run gofumpt (push) Successful in 2m18s
Vulncheck / Vulncheck (push) Successful in 2m55s
Build / Build Components (push) Successful in 3m11s
Tests and linters / Staticcheck (push) Successful in 3m23s
Pre-commit hooks / Pre-commit (push) Successful in 3m45s
Tests and linters / gopls check (push) Successful in 4m6s
Tests and linters / Lint (push) Successful in 4m29s
Tests and linters / Tests (push) Successful in 4m32s
Tests and linters / Tests with -race (push) Successful in 4m41s
All checks were successful
Tests and linters / Run gofumpt (pull_request) Successful in 2m11s
DCO action / DCO (pull_request) Successful in 2m27s
Vulncheck / Vulncheck (pull_request) Successful in 2m38s
Pre-commit hooks / Pre-commit (pull_request) Successful in 3m3s
Build / Build Components (pull_request) Successful in 3m20s
Tests and linters / gopls check (pull_request) Successful in 3m27s
Tests and linters / Staticcheck (pull_request) Successful in 4m0s
Tests and linters / Lint (pull_request) Successful in 4m39s
Tests and linters / Tests (pull_request) Successful in 5m9s
Tests and linters / Tests with -race (pull_request) Successful in 6m33s
Tests and linters / Run gofumpt (push) Successful in 2m18s
Vulncheck / Vulncheck (push) Successful in 2m55s
Build / Build Components (push) Successful in 3m11s
Tests and linters / Staticcheck (push) Successful in 3m23s
Pre-commit hooks / Pre-commit (push) Successful in 3m45s
Tests and linters / gopls check (push) Successful in 4m6s
Tests and linters / Lint (push) Successful in 4m29s
Tests and linters / Tests (push) Successful in 4m32s
Tests and linters / Tests with -race (push) Successful in 4m41s
Currently, it's allowed to inhume or lock an expired object. Consider the following scenario: 1) An user inhumes or locks an object 2) The object expires 3) GC hasn't yet deleted the object 4) The node loses the associated tombstone or lock 5) Another node replicates tombstone or lock to the first node In this case, the second node succeeds, which is the desired behavior. Signed-off-by: Aleksey Savchuk <a.savchuk@yadro.com>
This commit is contained in:
parent
9cabca9dfe
commit
432042c534
2 changed files with 106 additions and 0 deletions
|
@ -2,13 +2,17 @@ package engine
|
|||
|
||||
import (
|
||||
"context"
|
||||
"strconv"
|
||||
"testing"
|
||||
|
||||
"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"
|
||||
objectV2 "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/object"
|
||||
cidtest "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/id/test"
|
||||
objectSDK "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object"
|
||||
oidtest "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object/id/test"
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
||||
|
@ -84,3 +88,52 @@ func TestStorageEngine_Inhume(t *testing.T) {
|
|||
require.Empty(t, addrs)
|
||||
})
|
||||
}
|
||||
|
||||
func TestInhumeExpiredRegularObject(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
const currEpoch = 42
|
||||
const objectExpiresAfter = currEpoch - 1
|
||||
|
||||
engine := testNewEngine(t).setShardsNumAdditionalOpts(t, 1, func(_ int) []shard.Option {
|
||||
return []shard.Option{
|
||||
shard.WithDisabledGC(),
|
||||
shard.WithMetaBaseOptions(append(
|
||||
testGetDefaultMetabaseOptions(t),
|
||||
meta.WithEpochState(epochState{currEpoch}),
|
||||
)...),
|
||||
}
|
||||
}).prepare(t).engine
|
||||
|
||||
cnr := cidtest.ID()
|
||||
|
||||
generateAndPutObject := func() *objectSDK.Object {
|
||||
obj := testutil.GenerateObjectWithCID(cnr)
|
||||
testutil.AddAttribute(obj, objectV2.SysAttributeExpEpoch, strconv.Itoa(objectExpiresAfter))
|
||||
|
||||
var putPrm PutPrm
|
||||
putPrm.Object = obj
|
||||
require.NoError(t, engine.Put(context.Background(), putPrm))
|
||||
return obj
|
||||
}
|
||||
|
||||
t.Run("inhume with tombstone", func(t *testing.T) {
|
||||
obj := generateAndPutObject()
|
||||
ts := oidtest.Address()
|
||||
ts.SetContainer(cnr)
|
||||
|
||||
var prm InhumePrm
|
||||
prm.WithTarget(ts, object.AddressOf(obj))
|
||||
_, err := engine.Inhume(context.Background(), prm)
|
||||
require.NoError(t, err)
|
||||
})
|
||||
|
||||
t.Run("inhume without tombstone", func(t *testing.T) {
|
||||
obj := generateAndPutObject()
|
||||
|
||||
var prm InhumePrm
|
||||
prm.MarkAsGarbage(object.AddressOf(obj))
|
||||
_, err := engine.Inhume(context.Background(), prm)
|
||||
require.NoError(t, err)
|
||||
})
|
||||
}
|
||||
|
|
|
@ -292,3 +292,56 @@ func TestLockForceRemoval(t *testing.T) {
|
|||
_, err = e.Inhume(context.Background(), inhumePrm)
|
||||
require.NoError(t, err)
|
||||
}
|
||||
|
||||
func TestLockExpiredRegularObject(t *testing.T) {
|
||||
const currEpoch = 42
|
||||
const objectExpiresAfter = currEpoch - 1
|
||||
|
||||
engine := testNewEngine(t).setShardsNumAdditionalOpts(t, 1, func(_ int) []shard.Option {
|
||||
return []shard.Option{
|
||||
shard.WithDisabledGC(),
|
||||
shard.WithMetaBaseOptions(append(
|
||||
testGetDefaultMetabaseOptions(t),
|
||||
meta.WithEpochState(epochState{currEpoch}),
|
||||
)...),
|
||||
}
|
||||
}).prepare(t).engine
|
||||
|
||||
cnr := cidtest.ID()
|
||||
|
||||
object := testutil.GenerateObjectWithCID(cnr)
|
||||
testutil.AddAttribute(object, objectV2.SysAttributeExpEpoch, strconv.Itoa(objectExpiresAfter))
|
||||
|
||||
address := objectcore.AddressOf(object)
|
||||
|
||||
var putPrm PutPrm
|
||||
putPrm.Object = object
|
||||
require.NoError(t, engine.Put(context.Background(), putPrm))
|
||||
|
||||
var getPrm GetPrm
|
||||
var errNotFound *apistatus.ObjectNotFound
|
||||
|
||||
getPrm.WithAddress(address)
|
||||
_, err := engine.Get(context.Background(), getPrm)
|
||||
require.ErrorAs(t, err, &errNotFound)
|
||||
|
||||
t.Run("lock expired regular object", func(t *testing.T) {
|
||||
engine.Lock(context.Background(),
|
||||
address.Container(),
|
||||
oidtest.ID(),
|
||||
[]oid.ID{address.Object()},
|
||||
)
|
||||
|
||||
res, err := engine.IsLocked(context.Background(), objectcore.AddressOf(object))
|
||||
require.NoError(t, err)
|
||||
require.True(t, res)
|
||||
})
|
||||
|
||||
t.Run("get expired and locked regular object", func(t *testing.T) {
|
||||
getPrm.WithAddress(objectcore.AddressOf(object))
|
||||
|
||||
res, err := engine.Get(context.Background(), getPrm)
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, res.Object(), object)
|
||||
})
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue