mirror of
https://github.com/kopia/kopia.git
synced 2026-03-27 10:32:08 -04:00
* sharded: plumbed through blob.PutOptions * blob: removed blob.Storage.SetTime() method This was only used for `kopia repo sync-to` and got replaced with an equivalent blob.PutOptions.SetTime, which wehn set to non-zero time will attempt to set the modification time on a file. Since some providers don't support changing modification time, we are able to emulate it using per-blob metadata (on B2, Azure and GCS), sadly S3 is still unsupported, because it does not support returning metadata in list results. Also added PutOptions.GetTime, which when set to not nil, will populate the provided variable with actual time that got assigned to the blob. Added tests that verify that each provider supports GetTime and SetTime according to this spec. * blob: additional test coverage for filesystem storage * blob: added PutBlobAndGetMetadata() helper and used where appropriate * fixed test failures * pr feedback * Update repo/blob/azure/azure_storage.go Co-authored-by: Shikhar Mall <mall.shikhar.in@gmail.com> * Update repo/blob/filesystem/filesystem_storage.go Co-authored-by: Shikhar Mall <mall.shikhar.in@gmail.com> * Update repo/blob/filesystem/filesystem_storage.go Co-authored-by: Shikhar Mall <mall.shikhar.in@gmail.com> * blobtesting: fixed object_locking_map.go * blobtesting: removed SetTime from ObjectLockingMap Co-authored-by: Shikhar Mall <mall.shikhar.in@gmail.com>
116 lines
2.8 KiB
Go
116 lines
2.8 KiB
Go
// Package blobtesting implements storage with fault injection.
|
|
package blobtesting
|
|
|
|
import (
|
|
"context"
|
|
|
|
"github.com/kopia/kopia/internal/fault"
|
|
"github.com/kopia/kopia/repo/blob"
|
|
)
|
|
|
|
// Supported faulty methods.
|
|
const (
|
|
MethodGetBlob fault.Method = iota
|
|
MethodGetMetadata
|
|
MethodPutBlob
|
|
MethodDeleteBlob
|
|
MethodListBlobs
|
|
MethodListBlobsItem
|
|
MethodClose
|
|
MethodFlushCaches
|
|
)
|
|
|
|
// FaultyStorage implements fault injection for FaultyStorage.
|
|
type FaultyStorage struct {
|
|
base blob.Storage
|
|
|
|
fault.Set
|
|
}
|
|
|
|
// NewFaultyStorage creates new Storage with fault injection.
|
|
func NewFaultyStorage(base blob.Storage) *FaultyStorage {
|
|
return &FaultyStorage{
|
|
base: base,
|
|
}
|
|
}
|
|
|
|
// GetBlob implements blob.Storage.
|
|
func (s *FaultyStorage) GetBlob(ctx context.Context, id blob.ID, offset, length int64, output blob.OutputBuffer) error {
|
|
if ok, err := s.GetNextFault(ctx, MethodGetBlob, id, offset, length); ok {
|
|
return err
|
|
}
|
|
|
|
return s.base.GetBlob(ctx, id, offset, length, output)
|
|
}
|
|
|
|
// GetMetadata implements blob.Storage.
|
|
func (s *FaultyStorage) GetMetadata(ctx context.Context, id blob.ID) (blob.Metadata, error) {
|
|
if ok, err := s.GetNextFault(ctx, MethodGetMetadata, id); ok {
|
|
return blob.Metadata{}, err
|
|
}
|
|
|
|
return s.base.GetMetadata(ctx, id)
|
|
}
|
|
|
|
// PutBlob implements blob.Storage.
|
|
func (s *FaultyStorage) PutBlob(ctx context.Context, id blob.ID, data blob.Bytes, opts blob.PutOptions) error {
|
|
if ok, err := s.GetNextFault(ctx, MethodPutBlob, id); ok {
|
|
return err
|
|
}
|
|
|
|
return s.base.PutBlob(ctx, id, data, opts)
|
|
}
|
|
|
|
// DeleteBlob implements blob.Storage.
|
|
func (s *FaultyStorage) DeleteBlob(ctx context.Context, id blob.ID) error {
|
|
if ok, err := s.GetNextFault(ctx, MethodDeleteBlob, id); ok {
|
|
return err
|
|
}
|
|
|
|
return s.base.DeleteBlob(ctx, id)
|
|
}
|
|
|
|
// ListBlobs implements blob.Storage.
|
|
func (s *FaultyStorage) ListBlobs(ctx context.Context, prefix blob.ID, callback func(blob.Metadata) error) error {
|
|
if ok, err := s.GetNextFault(ctx, MethodListBlobs, prefix); ok {
|
|
return err
|
|
}
|
|
|
|
return s.base.ListBlobs(ctx, prefix, func(bm blob.Metadata) error {
|
|
if ok, err := s.GetNextFault(ctx, MethodListBlobsItem, prefix); ok {
|
|
return err
|
|
}
|
|
return callback(bm)
|
|
})
|
|
}
|
|
|
|
// Close implements blob.Storage.
|
|
func (s *FaultyStorage) Close(ctx context.Context) error {
|
|
if ok, err := s.GetNextFault(ctx, MethodClose); ok {
|
|
return err
|
|
}
|
|
|
|
return s.base.Close(ctx)
|
|
}
|
|
|
|
// ConnectionInfo implements blob.Storage.
|
|
func (s *FaultyStorage) ConnectionInfo() blob.ConnectionInfo {
|
|
return s.base.ConnectionInfo()
|
|
}
|
|
|
|
// DisplayName implements blob.Storage.
|
|
func (s *FaultyStorage) DisplayName() string {
|
|
return s.base.DisplayName()
|
|
}
|
|
|
|
// FlushCaches implements blob.Storage.
|
|
func (s *FaultyStorage) FlushCaches(ctx context.Context) error {
|
|
if ok, err := s.GetNextFault(ctx, MethodFlushCaches); ok {
|
|
return err
|
|
}
|
|
|
|
return s.base.FlushCaches(ctx)
|
|
}
|
|
|
|
var _ blob.Storage = (*FaultyStorage)(nil)
|