2020-04-15 20:20:16 +01:00
|
|
|
// Copyright (C) 2020 Storj Labs, Inc.
|
|
|
|
// See LICENSE for copying information.
|
|
|
|
|
|
|
|
package expireddeletion_test
|
|
|
|
|
|
|
|
import (
|
|
|
|
"context"
|
|
|
|
"strconv"
|
|
|
|
"testing"
|
|
|
|
"time"
|
|
|
|
|
|
|
|
"github.com/stretchr/testify/require"
|
|
|
|
"go.uber.org/zap"
|
|
|
|
|
|
|
|
"storj.io/common/memory"
|
|
|
|
"storj.io/common/pb"
|
|
|
|
"storj.io/common/testcontext"
|
|
|
|
"storj.io/common/testrand"
|
|
|
|
"storj.io/storj/private/testplanet"
|
|
|
|
"storj.io/storj/satellite"
|
|
|
|
"storj.io/storj/storage"
|
|
|
|
)
|
|
|
|
|
|
|
|
// TestExpiredDeletion does the following:
|
|
|
|
// * Set up a network with one storagenode
|
|
|
|
// * Upload three segments
|
|
|
|
// * Run the expired segment chore
|
|
|
|
// * Verify that all three segments still exist
|
|
|
|
// * Expire one of the segments
|
|
|
|
// * Run the expired segment chore
|
2020-07-16 15:18:02 +01:00
|
|
|
// * Verify that two segments still exist and the expired one has been deleted.
|
2020-04-15 20:20:16 +01:00
|
|
|
func TestExpiredDeletion(t *testing.T) {
|
|
|
|
testplanet.Run(t, testplanet.Config{
|
|
|
|
SatelliteCount: 1, StorageNodeCount: 1, UplinkCount: 1,
|
|
|
|
Reconfigure: testplanet.Reconfigure{
|
|
|
|
Satellite: func(log *zap.Logger, index int, config *satellite.Config) {
|
|
|
|
config.ExpiredDeletion.Interval = 500 * time.Millisecond
|
|
|
|
},
|
|
|
|
},
|
|
|
|
}, func(t *testing.T, ctx *testcontext.Context, planet *testplanet.Planet) {
|
|
|
|
satellite := planet.Satellites[0]
|
|
|
|
upl := planet.Uplinks[0]
|
|
|
|
expiredChore := satellite.Core.ExpiredDeletion.Chore
|
|
|
|
|
|
|
|
// Upload three objects
|
|
|
|
for i := 0; i < 4; i++ {
|
|
|
|
// 0 and 1 inline, 2 and 3 remote
|
|
|
|
testData := testrand.Bytes(8 * memory.KiB)
|
|
|
|
if i <= 1 {
|
|
|
|
testData = testrand.Bytes(1 * memory.KiB)
|
|
|
|
|
|
|
|
}
|
|
|
|
err := upl.Upload(ctx, satellite, "testbucket", "test/path/"+strconv.Itoa(i), testData)
|
|
|
|
require.NoError(t, err)
|
|
|
|
}
|
|
|
|
|
|
|
|
// Wait for next iteration of expired cleanup to finish
|
|
|
|
expiredChore.Loop.Restart()
|
|
|
|
expiredChore.Loop.TriggerWait()
|
|
|
|
|
|
|
|
// Verify that all four objects exist in metainfo
|
|
|
|
var expiredInline storage.ListItem
|
|
|
|
var expiredRemote storage.ListItem
|
|
|
|
i := 0
|
|
|
|
err := satellite.Metainfo.Database.Iterate(ctx, storage.IterateOptions{Recurse: true},
|
|
|
|
func(ctx context.Context, it storage.Iterator) error {
|
|
|
|
var item storage.ListItem
|
|
|
|
for it.Next(ctx, &item) {
|
|
|
|
if i == 1 {
|
|
|
|
expiredInline = item
|
|
|
|
} else if i == 3 {
|
|
|
|
expiredRemote = item
|
|
|
|
}
|
|
|
|
i++
|
|
|
|
}
|
|
|
|
return nil
|
|
|
|
})
|
|
|
|
require.NoError(t, err)
|
|
|
|
require.EqualValues(t, i, 4)
|
|
|
|
|
|
|
|
// Expire one inline segment and one remote segment
|
|
|
|
pointer := &pb.Pointer{}
|
|
|
|
err = pb.Unmarshal(expiredInline.Value, pointer)
|
|
|
|
require.NoError(t, err)
|
|
|
|
pointer.ExpirationDate = time.Now().Add(-24 * time.Hour)
|
|
|
|
newPointerBytes, err := pb.Marshal(pointer)
|
|
|
|
require.NoError(t, err)
|
|
|
|
err = satellite.Metainfo.Database.CompareAndSwap(ctx, expiredInline.Key, expiredInline.Value, newPointerBytes)
|
|
|
|
require.NoError(t, err)
|
|
|
|
|
|
|
|
err = pb.Unmarshal(expiredRemote.Value, pointer)
|
|
|
|
require.NoError(t, err)
|
|
|
|
pointer.ExpirationDate = time.Now().Add(-24 * time.Hour)
|
|
|
|
newPointerBytes, err = pb.Marshal(pointer)
|
|
|
|
require.NoError(t, err)
|
|
|
|
err = satellite.Metainfo.Database.CompareAndSwap(ctx, expiredRemote.Key, expiredRemote.Value, newPointerBytes)
|
|
|
|
require.NoError(t, err)
|
|
|
|
|
|
|
|
// Wait for next iteration of expired cleanup to finish
|
|
|
|
expiredChore.Loop.Restart()
|
|
|
|
expiredChore.Loop.TriggerWait()
|
|
|
|
|
|
|
|
// Verify that only two objects exist in metainfo
|
|
|
|
// And that the expired ones do not exist
|
|
|
|
i = 0
|
|
|
|
err = satellite.Metainfo.Database.Iterate(ctx, storage.IterateOptions{Recurse: true},
|
|
|
|
func(ctx context.Context, it storage.Iterator) error {
|
|
|
|
var item storage.ListItem
|
|
|
|
for it.Next(ctx, &item) {
|
|
|
|
require.False(t, item.Key.Equal(expiredInline.Key))
|
|
|
|
require.False(t, item.Key.Equal(expiredRemote.Key))
|
|
|
|
i++
|
|
|
|
}
|
|
|
|
return nil
|
|
|
|
})
|
|
|
|
require.NoError(t, err)
|
|
|
|
require.EqualValues(t, i, 2)
|
|
|
|
})
|
|
|
|
}
|