storj/storagenode/pieces/db_test.go
paul cannon 17bdb5e9e5
move piece info into files (#2629)
Deprecate the pieceinfo database, and start storing piece info as a header to
piece files. Institute a "storage format version" concept allowing us to handle
pieces stored under multiple different types of storage. Add a piece_expirations
table which will still be used to track expiration times, so we can query it, but
which should be much smaller than the pieceinfo database would be for the
same number of pieces. (Only pieces with expiration times need to be stored in piece_expirations, and we don't need to store large byte blobs like the serialized
order limit, etc.) Use specialized names for accessing any functionality related
only to dealing with V0 pieces (e.g., `store.V0PieceInfo()`). Move SpaceUsed-
type functionality under the purview of the piece store. Add some generic
interfaces for traversing all blobs or all pieces. Add lots of tests.
2019-08-07 20:47:30 -05:00

219 lines
6.0 KiB
Go

// Copyright (C) 2019 Storj Labs, Inc.
// See LICENSE for copying information.
package pieces_test
import (
"testing"
"time"
"github.com/google/go-cmp/cmp"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
"storj.io/storj/internal/testcontext"
"storj.io/storj/internal/testidentity"
"storj.io/storj/internal/testrand"
"storj.io/storj/pkg/pb"
"storj.io/storj/pkg/signing"
"storj.io/storj/pkg/storj"
"storj.io/storj/storagenode"
"storj.io/storj/storagenode/orders"
"storj.io/storj/storagenode/pieces"
"storj.io/storj/storagenode/storagenodedb/storagenodedbtest"
)
func TestV0PieceInfo(t *testing.T) {
storagenodedbtest.Run(t, func(t *testing.T, db storagenode.DB) {
ctx := testcontext.New(t)
defer ctx.Cleanup()
pieceinfos := db.V0PieceInfo().(pieces.V0PieceInfoDBForTest)
satellite0 := testidentity.MustPregeneratedSignedIdentity(0, storj.LatestIDVersion())
satellite1 := testidentity.MustPregeneratedSignedIdentity(1, storj.LatestIDVersion())
satellite2 := testidentity.MustPregeneratedSignedIdentity(2, storj.LatestIDVersion())
uplink0 := testidentity.MustPregeneratedSignedIdentity(3, storj.LatestIDVersion())
uplink1 := testidentity.MustPregeneratedSignedIdentity(4, storj.LatestIDVersion())
uplink2 := testidentity.MustPregeneratedSignedIdentity(5, storj.LatestIDVersion())
pieceid0 := storj.NewPieceID()
now := time.Now()
piecehash0, err := signing.SignPieceHash(ctx,
signing.SignerFromFullIdentity(uplink0),
&pb.PieceHash{
PieceId: pieceid0,
Hash: []byte{1, 2, 3, 4, 5},
})
require.NoError(t, err)
info0 := &pieces.Info{
SatelliteID: satellite0.ID,
PieceID: pieceid0,
PieceSize: 123,
PieceCreation: now,
PieceExpiration: now,
OrderLimit: &pb.OrderLimit{},
UplinkPieceHash: piecehash0,
}
piecehash1, err := signing.SignPieceHash(ctx,
signing.SignerFromFullIdentity(uplink1),
&pb.PieceHash{
PieceId: pieceid0,
Hash: []byte{1, 2, 3, 4, 5},
})
require.NoError(t, err)
info1 := &pieces.Info{
SatelliteID: satellite1.ID,
PieceID: pieceid0,
PieceSize: 123,
PieceCreation: now,
PieceExpiration: now,
OrderLimit: &pb.OrderLimit{},
UplinkPieceHash: piecehash1,
}
piecehash2, err := signing.SignPieceHash(ctx,
signing.SignerFromFullIdentity(uplink2),
&pb.PieceHash{
PieceId: pieceid0,
Hash: []byte{1, 2, 3, 4, 5},
})
require.NoError(t, err)
// use different timezones
location := time.FixedZone("XYZ", int((8 * time.Hour).Seconds()))
now2 := now.In(location)
info2 := &pieces.Info{
SatelliteID: satellite2.ID,
PieceID: pieceid0,
PieceSize: 123,
PieceCreation: now2,
PieceExpiration: now2,
OrderLimit: &pb.OrderLimit{},
UplinkPieceHash: piecehash2,
}
_, err = pieceinfos.Get(ctx, info0.SatelliteID, info0.PieceID)
require.Error(t, err, "getting element that doesn't exist")
// adding stuff
err = pieceinfos.Add(ctx, info0)
require.NoError(t, err)
err = pieceinfos.Add(ctx, info1)
require.NoError(t, err, "adding different satellite, but same pieceid")
err = pieceinfos.Add(ctx, info2)
require.NoError(t, err, "adding different satellite, but same pieceid")
err = pieceinfos.Add(ctx, info0)
require.Error(t, err, "adding duplicate")
// getting the added information
info0loaded, err := pieceinfos.Get(ctx, info0.SatelliteID, info0.PieceID)
require.NoError(t, err)
require.Empty(t, cmp.Diff(info0, info0loaded, cmp.Comparer(pb.Equal)))
info1loaded, err := pieceinfos.Get(ctx, info1.SatelliteID, info1.PieceID)
require.NoError(t, err)
require.Empty(t, cmp.Diff(info1, info1loaded, cmp.Comparer(pb.Equal)))
// getting no expired pieces
expired, err := pieceinfos.GetExpired(ctx, now.Add(-10*time.Hour), 10)
assert.NoError(t, err)
assert.Len(t, expired, 0)
// getting expired pieces
exp := now.Add(8 * 24 * time.Hour)
expired, err = pieceinfos.GetExpired(ctx, exp, 10)
assert.NoError(t, err)
assert.Len(t, expired, 3)
// mark info0 deletion as a failure
err = pieceinfos.DeleteFailed(ctx, info0.SatelliteID, info0.PieceID, exp)
assert.NoError(t, err)
// this shouldn't return info0
expired, err = pieceinfos.GetExpired(ctx, exp, 10)
assert.NoError(t, err)
assert.Len(t, expired, 2)
// deleting
err = pieceinfos.Delete(ctx, info0.SatelliteID, info0.PieceID)
require.NoError(t, err)
err = pieceinfos.Delete(ctx, info1.SatelliteID, info1.PieceID)
require.NoError(t, err)
// deleting expired pieces
err = pieceinfos.Delete(ctx, info2.SatelliteID, info2.PieceID)
require.NoError(t, err)
// duplicate deletion
err = pieceinfos.Delete(ctx, info2.SatelliteID, info2.PieceID)
require.NoError(t, err)
// getting after delete
_, err = pieceinfos.Get(ctx, info0.SatelliteID, info0.PieceID)
require.Error(t, err)
_, err = pieceinfos.Get(ctx, info1.SatelliteID, info1.PieceID)
require.Error(t, err)
})
}
func TestPieceInfo_Trivial(t *testing.T) {
storagenodedbtest.Run(t, func(t *testing.T, db storagenode.DB) {
ctx := testcontext.New(t)
defer ctx.Cleanup()
satelliteID, serial := testrand.NodeID(), testrand.SerialNumber()
{ // Ensure Enqueue works at all
err := db.Orders().Enqueue(ctx, &orders.Info{
Order: &pb.Order{},
Limit: &pb.OrderLimit{
SatelliteId: satelliteID,
SerialNumber: serial,
OrderExpiration: time.Now(),
},
})
require.NoError(t, err)
}
{ // Ensure ListUnsent works at all
_, err := db.Orders().ListUnsent(ctx, 1)
require.NoError(t, err)
}
{ // Ensure ListUnsentBySatellite works at all
_, err := db.Orders().ListUnsentBySatellite(ctx)
require.NoError(t, err)
}
{ // Ensure Archive works at all
err := db.Orders().Archive(ctx, orders.ArchiveRequest{
Satellite: satelliteID,
Serial: serial,
Status: orders.StatusAccepted,
})
require.NoError(t, err)
}
{ // Ensure ListArchived works at all
_, err := db.Orders().ListArchived(ctx, 1)
require.NoError(t, err)
}
})
}