2019-01-24 20:15:10 +00:00
|
|
|
// Copyright (C) 2019 Storj Labs, Inc.
|
2018-09-28 07:59:27 +01:00
|
|
|
// See LICENSE for copying information.
|
|
|
|
|
|
|
|
package filestore_test
|
|
|
|
|
|
|
|
import (
|
|
|
|
"errors"
|
|
|
|
"io"
|
|
|
|
"io/ioutil"
|
|
|
|
"os"
|
|
|
|
"path/filepath"
|
|
|
|
"testing"
|
|
|
|
|
2019-03-11 08:06:56 +00:00
|
|
|
"github.com/stretchr/testify/require"
|
|
|
|
|
|
|
|
"storj.io/storj/internal/testcontext"
|
2019-06-26 11:38:51 +01:00
|
|
|
"storj.io/storj/internal/testrand"
|
2018-09-28 07:59:27 +01:00
|
|
|
"storj.io/storj/storage"
|
|
|
|
"storj.io/storj/storage/filestore"
|
|
|
|
)
|
|
|
|
|
|
|
|
func TestStoreLoad(t *testing.T) {
|
|
|
|
const blobSize = 8 << 10
|
|
|
|
const repeatCount = 16
|
|
|
|
|
2019-03-11 08:06:56 +00:00
|
|
|
ctx := testcontext.New(t)
|
|
|
|
defer ctx.Cleanup()
|
2018-09-28 07:59:27 +01:00
|
|
|
|
2019-03-11 08:06:56 +00:00
|
|
|
store, err := filestore.NewAt(ctx.Dir("store"))
|
|
|
|
require.NoError(t, err)
|
2018-09-28 07:59:27 +01:00
|
|
|
|
2019-06-26 11:38:51 +01:00
|
|
|
data := testrand.Bytes(blobSize)
|
2018-09-28 07:59:27 +01:00
|
|
|
temp := make([]byte, len(data))
|
|
|
|
|
2019-03-11 08:06:56 +00:00
|
|
|
refs := []storage.BlobRef{}
|
2018-09-28 07:59:27 +01:00
|
|
|
|
2019-06-26 11:38:51 +01:00
|
|
|
namespace := testrand.Bytes(32)
|
|
|
|
|
2018-09-28 07:59:27 +01:00
|
|
|
// store without size
|
|
|
|
for i := 0; i < repeatCount; i++ {
|
2019-03-11 08:06:56 +00:00
|
|
|
ref := storage.BlobRef{
|
|
|
|
Namespace: namespace,
|
2019-06-26 11:38:51 +01:00
|
|
|
Key: testrand.Bytes(32),
|
2018-09-28 07:59:27 +01:00
|
|
|
}
|
2019-03-11 08:06:56 +00:00
|
|
|
refs = append(refs, ref)
|
|
|
|
|
|
|
|
writer, err := store.Create(ctx, ref, -1)
|
|
|
|
require.NoError(t, err)
|
|
|
|
|
|
|
|
n, err := writer.Write(data)
|
|
|
|
require.NoError(t, err)
|
|
|
|
require.Equal(t, n, len(data))
|
|
|
|
|
2019-06-05 14:06:06 +01:00
|
|
|
require.NoError(t, writer.Commit(ctx))
|
2019-03-18 14:29:54 +00:00
|
|
|
// after committing we should be able to call cancel without an error
|
2019-06-05 14:06:06 +01:00
|
|
|
require.NoError(t, writer.Cancel(ctx))
|
2019-03-18 14:29:54 +00:00
|
|
|
// two commits should fail
|
2019-06-05 14:06:06 +01:00
|
|
|
require.Error(t, writer.Commit(ctx))
|
2018-09-28 07:59:27 +01:00
|
|
|
}
|
|
|
|
|
2019-06-26 11:38:51 +01:00
|
|
|
namespace = testrand.Bytes(32)
|
2018-09-28 07:59:27 +01:00
|
|
|
// store with size
|
|
|
|
for i := 0; i < repeatCount; i++ {
|
2019-03-11 08:06:56 +00:00
|
|
|
ref := storage.BlobRef{
|
|
|
|
Namespace: namespace,
|
2019-06-26 11:38:51 +01:00
|
|
|
Key: testrand.Bytes(32),
|
2018-09-28 07:59:27 +01:00
|
|
|
}
|
2019-03-11 08:06:56 +00:00
|
|
|
refs = append(refs, ref)
|
|
|
|
|
|
|
|
writer, err := store.Create(ctx, ref, int64(len(data)))
|
|
|
|
require.NoError(t, err)
|
|
|
|
|
|
|
|
n, err := writer.Write(data)
|
|
|
|
require.NoError(t, err)
|
|
|
|
require.Equal(t, n, len(data))
|
|
|
|
|
2019-06-05 14:06:06 +01:00
|
|
|
require.NoError(t, writer.Commit(ctx))
|
2018-09-28 07:59:27 +01:00
|
|
|
}
|
|
|
|
|
2019-06-26 11:38:51 +01:00
|
|
|
namespace = testrand.Bytes(32)
|
2018-09-28 07:59:27 +01:00
|
|
|
// store with larger size
|
|
|
|
{
|
2019-03-11 08:06:56 +00:00
|
|
|
ref := storage.BlobRef{
|
|
|
|
Namespace: namespace,
|
2019-06-26 11:38:51 +01:00
|
|
|
Key: testrand.Bytes(32),
|
2018-09-28 07:59:27 +01:00
|
|
|
}
|
2019-03-11 08:06:56 +00:00
|
|
|
refs = append(refs, ref)
|
|
|
|
|
|
|
|
writer, err := store.Create(ctx, ref, int64(len(data)*2))
|
|
|
|
require.NoError(t, err)
|
|
|
|
|
|
|
|
n, err := writer.Write(data)
|
|
|
|
require.NoError(t, err)
|
|
|
|
require.Equal(t, n, len(data))
|
|
|
|
|
2019-06-05 14:06:06 +01:00
|
|
|
require.NoError(t, writer.Commit(ctx))
|
2018-09-28 07:59:27 +01:00
|
|
|
}
|
|
|
|
|
2019-06-26 11:38:51 +01:00
|
|
|
namespace = testrand.Bytes(32)
|
2018-09-28 07:59:27 +01:00
|
|
|
// store with error
|
|
|
|
{
|
2019-03-11 08:06:56 +00:00
|
|
|
ref := storage.BlobRef{
|
|
|
|
Namespace: namespace,
|
2019-06-26 11:38:51 +01:00
|
|
|
Key: testrand.Bytes(32),
|
2018-09-28 07:59:27 +01:00
|
|
|
}
|
2019-03-11 08:06:56 +00:00
|
|
|
|
|
|
|
writer, err := store.Create(ctx, ref, -1)
|
|
|
|
require.NoError(t, err)
|
|
|
|
|
|
|
|
n, err := writer.Write(data)
|
|
|
|
require.NoError(t, err)
|
|
|
|
require.Equal(t, n, len(data))
|
|
|
|
|
2019-06-05 14:06:06 +01:00
|
|
|
require.NoError(t, writer.Cancel(ctx))
|
2019-03-18 14:29:54 +00:00
|
|
|
// commit after cancel should return an error
|
2019-06-05 14:06:06 +01:00
|
|
|
require.Error(t, writer.Commit(ctx))
|
2019-03-11 08:06:56 +00:00
|
|
|
|
|
|
|
_, err = store.Open(ctx, ref)
|
|
|
|
require.Error(t, err)
|
2018-09-28 07:59:27 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
// try reading all the blobs
|
2019-03-11 08:06:56 +00:00
|
|
|
for _, ref := range refs {
|
|
|
|
reader, err := store.Open(ctx, ref)
|
|
|
|
require.NoError(t, err)
|
2018-09-28 07:59:27 +01:00
|
|
|
|
2019-03-11 08:06:56 +00:00
|
|
|
size, err := reader.Size()
|
|
|
|
require.NoError(t, err)
|
|
|
|
require.Equal(t, size, int64(len(data)))
|
2018-09-28 07:59:27 +01:00
|
|
|
|
|
|
|
_, err = io.ReadFull(reader, temp)
|
2019-03-11 08:06:56 +00:00
|
|
|
require.NoError(t, err)
|
2018-09-28 07:59:27 +01:00
|
|
|
|
2019-03-11 08:06:56 +00:00
|
|
|
require.NoError(t, reader.Close())
|
|
|
|
require.Equal(t, data, temp)
|
2018-09-28 07:59:27 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
// delete the blobs
|
2019-03-11 08:06:56 +00:00
|
|
|
for _, ref := range refs {
|
2018-09-28 07:59:27 +01:00
|
|
|
err := store.Delete(ctx, ref)
|
2019-03-11 08:06:56 +00:00
|
|
|
require.NoError(t, err)
|
2018-09-28 07:59:27 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
// try reading all the blobs
|
2019-03-11 08:06:56 +00:00
|
|
|
for _, ref := range refs {
|
|
|
|
_, err := store.Open(ctx, ref)
|
|
|
|
require.Error(t, err)
|
2018-09-28 07:59:27 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func TestDeleteWhileReading(t *testing.T) {
|
|
|
|
const blobSize = 8 << 10
|
2019-03-11 08:06:56 +00:00
|
|
|
const repeatCount = 16
|
2018-09-28 07:59:27 +01:00
|
|
|
|
2019-03-11 08:06:56 +00:00
|
|
|
ctx := testcontext.New(t)
|
|
|
|
defer ctx.Cleanup()
|
2018-09-28 07:59:27 +01:00
|
|
|
|
2019-03-11 08:06:56 +00:00
|
|
|
store, err := filestore.NewAt(ctx.Dir("store"))
|
|
|
|
require.NoError(t, err)
|
2018-09-28 07:59:27 +01:00
|
|
|
|
2019-06-26 11:38:51 +01:00
|
|
|
data := testrand.Bytes(blobSize)
|
2018-09-28 07:59:27 +01:00
|
|
|
|
2019-03-11 08:06:56 +00:00
|
|
|
ref := storage.BlobRef{
|
|
|
|
Namespace: []byte{0},
|
|
|
|
Key: []byte{1},
|
2018-09-28 07:59:27 +01:00
|
|
|
}
|
|
|
|
|
2019-03-11 08:06:56 +00:00
|
|
|
writer, err := store.Create(ctx, ref, -1)
|
|
|
|
require.NoError(t, err)
|
|
|
|
|
|
|
|
_, err = writer.Write(data)
|
|
|
|
require.NoError(t, err)
|
|
|
|
|
|
|
|
// loading uncommitted file should fail
|
|
|
|
_, err = store.Open(ctx, ref)
|
|
|
|
require.Error(t, err, "loading uncommitted file should fail")
|
|
|
|
|
|
|
|
// commit the file
|
2019-06-05 14:06:06 +01:00
|
|
|
err = writer.Commit(ctx)
|
2019-03-11 08:06:56 +00:00
|
|
|
require.NoError(t, err, "commit the file")
|
|
|
|
|
|
|
|
// open a reader
|
|
|
|
reader, err := store.Open(ctx, ref)
|
|
|
|
require.NoError(t, err, "open a reader")
|
|
|
|
|
2018-09-28 07:59:27 +01:00
|
|
|
// double close, just in case
|
2019-03-11 08:06:56 +00:00
|
|
|
defer func() { _ = reader.Close() }()
|
2018-09-28 07:59:27 +01:00
|
|
|
|
2019-03-11 08:06:56 +00:00
|
|
|
// delete while reading
|
|
|
|
err = store.Delete(ctx, ref)
|
|
|
|
require.NoError(t, err, "delete while reading")
|
2018-09-28 07:59:27 +01:00
|
|
|
|
2019-03-11 08:06:56 +00:00
|
|
|
// opening deleted file should fail
|
|
|
|
_, err = store.Open(ctx, ref)
|
|
|
|
require.Error(t, err, "opening deleted file should fail")
|
2018-09-28 07:59:27 +01:00
|
|
|
|
2019-03-11 08:06:56 +00:00
|
|
|
// read all content
|
|
|
|
result, err := ioutil.ReadAll(reader)
|
|
|
|
require.NoError(t, err, "read all content")
|
2018-09-28 07:59:27 +01:00
|
|
|
|
2019-03-11 08:06:56 +00:00
|
|
|
// finally close reader
|
|
|
|
err = reader.Close()
|
|
|
|
require.NoError(t, err)
|
|
|
|
|
|
|
|
// should be able to read the full content
|
|
|
|
require.Equal(t, data, result)
|
|
|
|
|
|
|
|
// collect trash
|
|
|
|
_ = store.GarbageCollect(ctx)
|
2018-09-28 07:59:27 +01:00
|
|
|
|
|
|
|
// flaky test, for checking whether files have been actually deleted from disk
|
2019-03-11 08:06:56 +00:00
|
|
|
err = filepath.Walk(ctx.Dir("store"), func(path string, info os.FileInfo, err error) error {
|
2018-09-28 07:59:27 +01:00
|
|
|
if info.IsDir() {
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
return errors.New("found file " + path)
|
|
|
|
})
|
|
|
|
if err != nil {
|
|
|
|
t.Fatal(err)
|
|
|
|
}
|
|
|
|
}
|