2018-05-12 19:40:31 +00:00
|
|
|
package archiver
|
|
|
|
|
|
|
|
import (
|
|
|
|
"context"
|
|
|
|
"fmt"
|
|
|
|
"runtime"
|
2022-10-07 18:23:38 +00:00
|
|
|
"sync"
|
2018-05-12 19:40:31 +00:00
|
|
|
"sync/atomic"
|
|
|
|
"testing"
|
|
|
|
|
|
|
|
"github.com/restic/restic/internal/errors"
|
2022-06-12 12:43:43 +00:00
|
|
|
"github.com/restic/restic/internal/index"
|
2018-05-12 19:40:31 +00:00
|
|
|
"github.com/restic/restic/internal/restic"
|
2022-05-27 17:08:50 +00:00
|
|
|
"golang.org/x/sync/errgroup"
|
2018-05-12 19:40:31 +00:00
|
|
|
)
|
|
|
|
|
|
|
|
var errTest = errors.New("test error")
|
|
|
|
|
|
|
|
type saveFail struct {
|
2020-07-25 19:19:46 +00:00
|
|
|
idx restic.MasterIndex
|
2018-05-12 19:40:31 +00:00
|
|
|
cnt int32
|
|
|
|
failAt int32
|
|
|
|
}
|
|
|
|
|
2023-05-18 17:27:38 +00:00
|
|
|
func (b *saveFail) SaveBlob(_ context.Context, _ restic.BlobType, _ []byte, id restic.ID, _ bool) (restic.ID, bool, int, error) {
|
2018-05-12 19:40:31 +00:00
|
|
|
val := atomic.AddInt32(&b.cnt, 1)
|
|
|
|
if val == b.failAt {
|
2022-05-01 12:26:57 +00:00
|
|
|
return restic.ID{}, false, 0, errTest
|
2018-05-12 19:40:31 +00:00
|
|
|
}
|
|
|
|
|
2022-05-01 12:26:57 +00:00
|
|
|
return id, false, 0, nil
|
2018-05-12 19:40:31 +00:00
|
|
|
}
|
|
|
|
|
2020-07-25 19:19:46 +00:00
|
|
|
func (b *saveFail) Index() restic.MasterIndex {
|
2018-05-12 19:40:31 +00:00
|
|
|
return b.idx
|
|
|
|
}
|
|
|
|
|
|
|
|
func TestBlobSaver(t *testing.T) {
|
|
|
|
ctx, cancel := context.WithCancel(context.Background())
|
|
|
|
defer cancel()
|
|
|
|
|
2022-05-27 17:08:50 +00:00
|
|
|
wg, ctx := errgroup.WithContext(ctx)
|
2018-05-12 19:40:31 +00:00
|
|
|
saver := &saveFail{
|
2022-06-12 12:43:43 +00:00
|
|
|
idx: index.NewMasterIndex(),
|
2018-05-12 19:40:31 +00:00
|
|
|
}
|
|
|
|
|
2022-05-27 17:08:50 +00:00
|
|
|
b := NewBlobSaver(ctx, wg, saver, uint(runtime.NumCPU()))
|
2018-05-12 19:40:31 +00:00
|
|
|
|
2022-10-07 18:23:38 +00:00
|
|
|
var wait sync.WaitGroup
|
|
|
|
var results []SaveBlobResponse
|
2022-11-10 19:19:37 +00:00
|
|
|
var lock sync.Mutex
|
2018-05-12 19:40:31 +00:00
|
|
|
|
2022-10-07 18:23:38 +00:00
|
|
|
wait.Add(20)
|
2018-05-12 19:40:31 +00:00
|
|
|
for i := 0; i < 20; i++ {
|
|
|
|
buf := &Buffer{Data: []byte(fmt.Sprintf("foo%d", i))}
|
2022-10-07 18:23:38 +00:00
|
|
|
idx := i
|
2022-11-10 19:19:37 +00:00
|
|
|
lock.Lock()
|
2022-10-07 18:23:38 +00:00
|
|
|
results = append(results, SaveBlobResponse{})
|
2022-11-10 19:19:37 +00:00
|
|
|
lock.Unlock()
|
2022-10-07 18:23:38 +00:00
|
|
|
b.Save(ctx, restic.DataBlob, buf, func(res SaveBlobResponse) {
|
2022-11-10 19:19:37 +00:00
|
|
|
lock.Lock()
|
2022-10-07 18:23:38 +00:00
|
|
|
results[idx] = res
|
2022-11-10 19:19:37 +00:00
|
|
|
lock.Unlock()
|
2022-10-07 18:23:38 +00:00
|
|
|
wait.Done()
|
|
|
|
})
|
2018-05-12 19:40:31 +00:00
|
|
|
}
|
|
|
|
|
2022-10-07 18:23:38 +00:00
|
|
|
wait.Wait()
|
|
|
|
for i, sbr := range results {
|
2022-05-22 13:14:25 +00:00
|
|
|
if sbr.known {
|
2018-05-12 19:40:31 +00:00
|
|
|
t.Errorf("blob %v is known, that should not be the case", i)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-05-27 17:08:50 +00:00
|
|
|
b.TriggerShutdown()
|
2018-05-12 19:40:31 +00:00
|
|
|
|
2022-05-27 17:08:50 +00:00
|
|
|
err := wg.Wait()
|
2018-05-12 19:40:31 +00:00
|
|
|
if err != nil {
|
|
|
|
t.Fatal(err)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func TestBlobSaverError(t *testing.T) {
|
|
|
|
var tests = []struct {
|
|
|
|
blobs int
|
|
|
|
failAt int
|
|
|
|
}{
|
|
|
|
{20, 2},
|
|
|
|
{20, 5},
|
|
|
|
{20, 15},
|
|
|
|
{200, 150},
|
|
|
|
}
|
|
|
|
|
|
|
|
for _, test := range tests {
|
|
|
|
t.Run("", func(t *testing.T) {
|
|
|
|
ctx, cancel := context.WithCancel(context.Background())
|
|
|
|
defer cancel()
|
|
|
|
|
2022-05-27 17:08:50 +00:00
|
|
|
wg, ctx := errgroup.WithContext(ctx)
|
2018-05-12 19:40:31 +00:00
|
|
|
saver := &saveFail{
|
2022-06-12 12:43:43 +00:00
|
|
|
idx: index.NewMasterIndex(),
|
2018-05-12 19:40:31 +00:00
|
|
|
failAt: int32(test.failAt),
|
|
|
|
}
|
|
|
|
|
2022-05-27 17:08:50 +00:00
|
|
|
b := NewBlobSaver(ctx, wg, saver, uint(runtime.NumCPU()))
|
2018-05-12 19:40:31 +00:00
|
|
|
|
|
|
|
for i := 0; i < test.blobs; i++ {
|
|
|
|
buf := &Buffer{Data: []byte(fmt.Sprintf("foo%d", i))}
|
2022-10-07 18:23:38 +00:00
|
|
|
b.Save(ctx, restic.DataBlob, buf, func(res SaveBlobResponse) {})
|
2018-05-12 19:40:31 +00:00
|
|
|
}
|
|
|
|
|
2022-05-27 17:08:50 +00:00
|
|
|
b.TriggerShutdown()
|
2018-05-12 19:40:31 +00:00
|
|
|
|
2022-05-27 17:08:50 +00:00
|
|
|
err := wg.Wait()
|
2018-05-12 19:40:31 +00:00
|
|
|
if err == nil {
|
|
|
|
t.Errorf("expected error not found")
|
|
|
|
}
|
|
|
|
|
|
|
|
if err != errTest {
|
|
|
|
t.Fatalf("unexpected error found: %v", err)
|
|
|
|
}
|
|
|
|
})
|
|
|
|
}
|
|
|
|
}
|