2015-05-09 23:52:03 +02:00
package repository_test
2015-02-16 19:32:36 +01:00
import (
"bytes"
2017-06-05 23:56:59 +02:00
"context"
2015-02-16 19:32:36 +01:00
"crypto/sha256"
2015-02-16 20:00:23 +01:00
"io"
2017-01-13 12:20:37 +01:00
"math/rand"
2015-07-04 16:52:17 +02:00
"path/filepath"
2024-06-05 22:46:34 +02:00
"strings"
2024-05-09 15:26:41 +02:00
"sync"
2015-02-16 19:32:36 +01:00
"testing"
2017-01-13 12:20:37 +01:00
"time"
2015-02-16 19:32:36 +01:00
2023-10-01 11:40:12 +02:00
"github.com/restic/restic/internal/backend"
2024-05-24 23:04:06 +02:00
"github.com/restic/restic/internal/backend/cache"
2021-09-19 20:02:38 +02:00
"github.com/restic/restic/internal/backend/local"
2024-05-09 21:22:19 +02:00
"github.com/restic/restic/internal/backend/mem"
2022-03-21 20:38:53 +01:00
"github.com/restic/restic/internal/crypto"
2024-05-09 18:59:29 +02:00
"github.com/restic/restic/internal/errors"
2017-07-23 14:21:03 +02:00
"github.com/restic/restic/internal/repository"
2024-05-24 23:06:44 +02:00
"github.com/restic/restic/internal/repository/index"
2017-07-24 17:42:25 +02:00
"github.com/restic/restic/internal/restic"
2024-05-09 21:22:19 +02:00
"github.com/restic/restic/internal/test"
2017-10-02 15:06:39 +02:00
rtest "github.com/restic/restic/internal/test"
2021-08-07 22:52:05 +02:00
"golang.org/x/sync/errgroup"
2015-02-16 19:32:36 +01:00
)
2015-02-16 20:00:23 +01:00
var testSizes = [ ] int { 5 , 23 , 2 << 18 + 23 , 1 << 20 }
2017-01-13 12:20:37 +01:00
var rnd = rand . New ( rand . NewSource ( time . Now ( ) . UnixNano ( ) ) )
2015-04-26 17:44:38 +02:00
func TestSave ( t * testing . T ) {
2024-01-20 21:50:23 +01:00
repository . TestAllVersions ( t , testSavePassID )
repository . TestAllVersions ( t , testSaveCalculateID )
2022-04-29 23:16:16 +02:00
}
2024-01-20 21:50:23 +01:00
func testSavePassID ( t * testing . T , version uint ) {
testSave ( t , version , false )
2015-04-26 17:44:38 +02:00
}
2024-01-20 21:50:23 +01:00
func testSaveCalculateID ( t * testing . T , version uint ) {
testSave ( t , version , true )
2022-04-29 23:16:16 +02:00
}
2024-01-20 21:50:23 +01:00
func testSave ( t * testing . T , version uint , calculateID bool ) {
2024-05-10 16:59:09 +02:00
repo , _ := repository . TestRepositoryWithVersion ( t , version )
2015-02-16 20:00:23 +01:00
for _ , size := range testSizes {
data := make ( [ ] byte , size )
2017-01-13 12:20:37 +01:00
_ , err := io . ReadFull ( rnd , data )
2017-10-02 15:06:39 +02:00
rtest . OK ( t , err )
2015-02-16 20:00:23 +01:00
2016-08-31 20:29:54 +02:00
id := restic . Hash ( data )
2015-02-16 20:00:23 +01:00
2021-08-07 22:52:05 +02:00
var wg errgroup . Group
repo . StartPackUploader ( context . TODO ( ) , & wg )
2015-02-16 20:00:23 +01:00
// save
2024-01-20 21:50:23 +01:00
inputID := restic . ID { }
if ! calculateID {
inputID = id
}
sid , _ , _ , err := repo . SaveBlob ( context . TODO ( ) , restic . DataBlob , data , inputID , false )
2017-10-02 15:06:39 +02:00
rtest . OK ( t , err )
2024-01-20 21:50:23 +01:00
rtest . Equals ( t , id , sid )
2015-02-16 20:00:23 +01:00
2017-11-22 06:27:29 -05:00
rtest . OK ( t , repo . Flush ( context . Background ( ) ) )
2015-04-26 17:44:38 +02:00
2015-02-16 20:00:23 +01:00
// read back
2020-03-10 16:41:22 +01:00
buf , err := repo . LoadBlob ( context . TODO ( ) , restic . DataBlob , id , nil )
2017-10-02 15:06:39 +02:00
rtest . OK ( t , err )
2020-03-10 16:41:22 +01:00
rtest . Equals ( t , size , len ( buf ) )
2015-02-16 20:00:23 +01:00
2017-10-02 15:06:39 +02:00
rtest . Assert ( t , len ( buf ) == len ( data ) ,
2015-02-16 20:00:23 +01:00
"number of bytes read back does not match: expected %d, got %d" ,
len ( data ) , len ( buf ) )
2017-10-02 15:06:39 +02:00
rtest . Assert ( t , bytes . Equal ( buf , data ) ,
2015-02-16 20:00:23 +01:00
"data does not match: expected %02x, got %02x" ,
data , buf )
}
}
2016-05-08 13:13:29 +02:00
func BenchmarkSaveAndEncrypt ( t * testing . B ) {
2022-04-29 23:16:16 +02:00
repository . BenchmarkAllVersions ( t , benchmarkSaveAndEncrypt )
}
func benchmarkSaveAndEncrypt ( t * testing . B , version uint ) {
2024-05-10 16:59:09 +02:00
repo , _ := repository . TestRepositoryWithVersion ( t , version )
2015-02-16 20:00:23 +01:00
size := 4 << 20 // 4MiB
data := make ( [ ] byte , size )
2017-01-13 12:20:37 +01:00
_ , err := io . ReadFull ( rnd , data )
2017-10-02 15:06:39 +02:00
rtest . OK ( t , err )
2015-02-16 20:00:23 +01:00
2016-08-31 20:29:54 +02:00
id := restic . ID ( sha256 . Sum256 ( data ) )
2022-10-25 17:21:24 +02:00
var wg errgroup . Group
repo . StartPackUploader ( context . Background ( ) , & wg )
2015-02-16 20:00:23 +01:00
2020-02-26 23:26:11 +01:00
t . ReportAllocs ( )
2015-02-16 20:00:23 +01:00
t . ResetTimer ( )
t . SetBytes ( int64 ( size ) )
for i := 0 ; i < t . N ; i ++ {
2022-05-01 14:26:57 +02:00
_ , _ , _ , err = repo . SaveBlob ( context . TODO ( ) , restic . DataBlob , data , id , true )
2017-10-02 15:06:39 +02:00
rtest . OK ( t , err )
2015-02-16 20:00:23 +01:00
}
}
2015-02-17 23:05:23 +01:00
2017-01-24 11:25:33 +01:00
func TestLoadBlob ( t * testing . T ) {
2022-04-29 23:16:16 +02:00
repository . TestAllVersions ( t , testLoadBlob )
}
func testLoadBlob ( t * testing . T , version uint ) {
2024-05-10 16:59:09 +02:00
repo , _ := repository . TestRepositoryWithVersion ( t , version )
2017-01-24 11:25:33 +01:00
length := 1000000
2022-06-12 14:48:30 +02:00
buf := crypto . NewBlobBuffer ( length )
2017-01-24 11:25:33 +01:00
_ , err := io . ReadFull ( rnd , buf )
2017-10-02 15:06:39 +02:00
rtest . OK ( t , err )
2017-01-24 11:25:33 +01:00
2021-08-07 22:52:05 +02:00
var wg errgroup . Group
repo . StartPackUploader ( context . TODO ( ) , & wg )
2022-05-01 14:26:57 +02:00
id , _ , _ , err := repo . SaveBlob ( context . TODO ( ) , restic . DataBlob , buf , restic . ID { } , false )
2017-10-02 15:06:39 +02:00
rtest . OK ( t , err )
2017-11-22 06:27:29 -05:00
rtest . OK ( t , repo . Flush ( context . Background ( ) ) )
2017-01-24 11:25:33 +01:00
2022-06-12 14:48:30 +02:00
base := crypto . CiphertextLength ( length )
2020-03-10 16:41:22 +01:00
for _ , testlength := range [ ] int { 0 , base - 20 , base - 1 , base , base + 7 , base + 15 , base + 1000 } {
2017-01-24 11:25:33 +01:00
buf = make ( [ ] byte , 0 , testlength )
2020-03-10 16:41:22 +01:00
buf , err := repo . LoadBlob ( context . TODO ( ) , restic . DataBlob , id , buf )
2017-01-24 11:25:33 +01:00
if err != nil {
t . Errorf ( "LoadBlob() returned an error for buffer size %v: %v" , testlength , err )
continue
}
2020-03-10 16:41:22 +01:00
if len ( buf ) != length {
t . Errorf ( "LoadBlob() returned the wrong number of bytes: want %v, got %v" , length , len ( buf ) )
2017-01-24 11:25:33 +01:00
continue
}
}
}
2024-05-09 21:22:19 +02:00
func TestLoadBlobBroken ( t * testing . T ) {
be := mem . New ( )
2024-05-10 16:59:09 +02:00
repo , _ := repository . TestRepositoryWithBackend ( t , & damageOnceBackend { Backend : be } , restic . StableRepoVersion , repository . Options { } )
2024-05-09 21:22:19 +02:00
buf := test . Random ( 42 , 1000 )
var wg errgroup . Group
repo . StartPackUploader ( context . TODO ( ) , & wg )
id , _ , _ , err := repo . SaveBlob ( context . TODO ( ) , restic . TreeBlob , buf , restic . ID { } , false )
rtest . OK ( t , err )
rtest . OK ( t , repo . Flush ( context . Background ( ) ) )
// setup cache after saving the blob to make sure that the damageOnceBackend damages the cached data
c := cache . TestNewCache ( t )
repo . UseCache ( c )
data , err := repo . LoadBlob ( context . TODO ( ) , restic . TreeBlob , id , nil )
rtest . OK ( t , err )
rtest . Assert ( t , bytes . Equal ( buf , data ) , "data mismatch" )
2024-05-19 14:56:17 +02:00
pack := repo . LookupBlob ( restic . TreeBlob , id ) [ 0 ] . PackID
2024-05-09 21:22:19 +02:00
rtest . Assert ( t , c . Has ( backend . Handle { Type : restic . PackFile , Name : pack . String ( ) } ) , "expected tree pack to be cached" )
}
2017-01-13 12:20:37 +01:00
func BenchmarkLoadBlob ( b * testing . B ) {
2022-04-29 23:16:16 +02:00
repository . BenchmarkAllVersions ( b , benchmarkLoadBlob )
}
func benchmarkLoadBlob ( b * testing . B , version uint ) {
2024-05-10 16:59:09 +02:00
repo , _ := repository . TestRepositoryWithVersion ( b , version )
2017-01-13 12:20:37 +01:00
length := 1000000
2022-06-12 14:48:30 +02:00
buf := crypto . NewBlobBuffer ( length )
2017-01-13 12:20:37 +01:00
_ , err := io . ReadFull ( rnd , buf )
2017-10-02 15:06:39 +02:00
rtest . OK ( b , err )
2017-01-13 12:20:37 +01:00
2021-08-07 22:52:05 +02:00
var wg errgroup . Group
repo . StartPackUploader ( context . TODO ( ) , & wg )
2022-05-01 14:26:57 +02:00
id , _ , _ , err := repo . SaveBlob ( context . TODO ( ) , restic . DataBlob , buf , restic . ID { } , false )
2017-10-02 15:06:39 +02:00
rtest . OK ( b , err )
2017-11-22 06:27:29 -05:00
rtest . OK ( b , repo . Flush ( context . Background ( ) ) )
2017-01-13 12:20:37 +01:00
b . ResetTimer ( )
b . SetBytes ( int64 ( length ) )
for i := 0 ; i < b . N ; i ++ {
2020-03-10 16:41:22 +01:00
var err error
buf , err = repo . LoadBlob ( context . TODO ( ) , restic . DataBlob , id , buf )
2020-04-28 07:57:29 +02:00
// Checking the SHA-256 with restic.Hash can make up 38% of the time
// spent in this loop, so pause the timer.
b . StopTimer ( )
2017-10-02 15:06:39 +02:00
rtest . OK ( b , err )
2020-03-10 16:41:22 +01:00
if len ( buf ) != length {
b . Errorf ( "wanted %d bytes, got %d" , length , len ( buf ) )
2017-01-13 12:20:37 +01:00
}
2020-03-10 16:41:22 +01:00
id2 := restic . Hash ( buf )
2017-01-13 12:20:37 +01:00
if ! id . Equal ( id2 ) {
b . Errorf ( "wrong data returned, wanted %v, got %v" , id . Str ( ) , id2 . Str ( ) )
}
2020-04-28 07:57:29 +02:00
b . StartTimer ( )
2017-01-13 12:20:37 +01:00
}
}
2022-02-13 00:01:27 +01:00
func BenchmarkLoadUnpacked ( b * testing . B ) {
2022-04-29 23:16:16 +02:00
repository . BenchmarkAllVersions ( b , benchmarkLoadUnpacked )
}
func benchmarkLoadUnpacked ( b * testing . B , version uint ) {
2024-05-10 16:59:09 +02:00
repo , _ := repository . TestRepositoryWithVersion ( b , version )
2017-01-13 20:56:50 +01:00
length := 1000000
2022-06-12 14:48:30 +02:00
buf := crypto . NewBlobBuffer ( length )
2017-01-13 20:56:50 +01:00
_ , err := io . ReadFull ( rnd , buf )
2017-10-02 15:06:39 +02:00
rtest . OK ( b , err )
2017-01-13 20:56:50 +01:00
dataID := restic . Hash ( buf )
2020-08-16 11:16:38 +02:00
storageID , err := repo . SaveUnpacked ( context . TODO ( ) , restic . PackFile , buf )
2017-10-02 15:06:39 +02:00
rtest . OK ( b , err )
// rtest.OK(b, repo.Flush())
2017-01-13 20:56:50 +01:00
b . ResetTimer ( )
b . SetBytes ( int64 ( length ) )
for i := 0 ; i < b . N ; i ++ {
2023-01-27 15:01:54 +01:00
data , err := repo . LoadUnpacked ( context . TODO ( ) , restic . PackFile , storageID )
2017-10-02 15:06:39 +02:00
rtest . OK ( b , err )
2020-04-28 07:57:29 +02:00
// See comment in BenchmarkLoadBlob.
b . StopTimer ( )
2017-01-13 20:56:50 +01:00
if len ( data ) != length {
b . Errorf ( "wanted %d bytes, got %d" , length , len ( data ) )
}
id2 := restic . Hash ( data )
if ! dataID . Equal ( id2 ) {
b . Errorf ( "wrong data returned, wanted %v, got %v" , storageID . Str ( ) , id2 . Str ( ) )
}
2020-04-28 07:57:29 +02:00
b . StartTimer ( )
2017-01-13 20:56:50 +01:00
}
}
2015-07-04 16:52:17 +02:00
var repoFixture = filepath . Join ( "testdata" , "test-repo.tar.gz" )
2015-08-08 12:22:17 +02:00
func TestRepositoryLoadIndex ( t * testing . T ) {
2024-05-10 16:59:09 +02:00
repo , _ , cleanup := repository . TestFromFixture ( t , repoFixture )
2016-09-04 14:29:04 +02:00
defer cleanup ( )
2023-07-15 22:48:30 -04:00
rtest . OK ( t , repo . LoadIndex ( context . TODO ( ) , nil ) )
2015-07-04 16:52:17 +02:00
}
2020-11-07 18:53:59 +01:00
// loadIndex loads the index id from backend and returns it.
2024-01-19 22:44:50 +01:00
func loadIndex ( ctx context . Context , repo restic . LoaderUnpacked , id restic . ID ) ( * index . Index , error ) {
2023-01-27 15:01:54 +01:00
buf , err := repo . LoadUnpacked ( ctx , restic . IndexFile , id )
2020-11-07 18:53:59 +01:00
if err != nil {
return nil , err
}
2024-08-26 20:07:21 +02:00
return index . DecodeIndex ( buf , id )
2020-11-07 18:53:59 +01:00
}
2021-09-19 20:02:38 +02:00
func TestRepositoryLoadUnpackedBroken ( t * testing . T ) {
2024-05-10 16:59:09 +02:00
repo , be := repository . TestRepositoryWithVersion ( t , 0 )
2021-09-19 20:02:38 +02:00
data := rtest . Random ( 23 , 12345 )
id := restic . Hash ( data )
2023-10-01 11:40:12 +02:00
h := backend . Handle { Type : restic . IndexFile , Name : id . String ( ) }
2021-09-19 20:02:38 +02:00
// damage buffer
data [ 0 ] ^ = 0xff
// store broken file
2024-05-10 16:59:09 +02:00
err := be . Save ( context . TODO ( ) , h , backend . NewByteReader ( data , be . Hasher ( ) ) )
2021-09-19 20:02:38 +02:00
rtest . OK ( t , err )
2023-01-27 15:01:54 +01:00
_ , err = repo . LoadUnpacked ( context . TODO ( ) , restic . IndexFile , id )
2024-05-09 18:59:29 +02:00
rtest . Assert ( t , errors . Is ( err , restic . ErrInvalidData ) , "unexpected error: %v" , err )
2021-09-19 20:02:38 +02:00
}
type damageOnceBackend struct {
2023-10-01 11:40:12 +02:00
backend . Backend
2024-05-09 15:26:41 +02:00
m sync . Map
2021-09-19 20:02:38 +02:00
}
2023-10-01 11:40:12 +02:00
func ( be * damageOnceBackend ) Load ( ctx context . Context , h backend . Handle , length int , offset int64 , fn func ( rd io . Reader ) error ) error {
2021-09-19 20:02:38 +02:00
// don't break the config file as we can't retry it
if h . Type == restic . ConfigFile {
return be . Backend . Load ( ctx , h , length , offset , fn )
}
2024-05-09 15:26:41 +02:00
2024-05-09 21:39:52 +02:00
h . IsMetadata = false
2024-05-09 23:26:21 +02:00
_ , isRetry := be . m . LoadOrStore ( h , true )
if ! isRetry {
2024-05-09 15:26:41 +02:00
// return broken data on the first try
2024-05-09 21:22:19 +02:00
offset ++
2021-09-19 20:02:38 +02:00
}
2024-05-09 15:26:41 +02:00
return be . Backend . Load ( ctx , h , length , offset , fn )
2021-09-19 20:02:38 +02:00
}
func TestRepositoryLoadUnpackedRetryBroken ( t * testing . T ) {
repodir , cleanup := rtest . Env ( t , repoFixture )
defer cleanup ( )
be , err := local . Open ( context . TODO ( ) , local . Config { Path : repodir , Connections : 2 } )
rtest . OK ( t , err )
2024-02-24 21:45:24 +01:00
repo := repository . TestOpenBackend ( t , & damageOnceBackend { Backend : be } )
2021-09-19 20:02:38 +02:00
2023-07-15 22:48:30 -04:00
rtest . OK ( t , repo . LoadIndex ( context . TODO ( ) , nil ) )
2021-09-19 20:02:38 +02:00
}
2015-07-04 16:52:17 +02:00
func BenchmarkLoadIndex ( b * testing . B ) {
2022-04-29 23:16:16 +02:00
repository . BenchmarkAllVersions ( b , benchmarkLoadIndex )
}
func benchmarkLoadIndex ( b * testing . B , version uint ) {
2017-01-13 21:39:40 +01:00
repository . TestUseLowSecurityKDFParameters ( b )
2024-05-10 16:59:09 +02:00
repo , be := repository . TestRepositoryWithVersion ( b , version )
2022-06-12 14:43:43 +02:00
idx := index . NewIndex ( )
2017-01-13 21:39:40 +01:00
for i := 0 ; i < 5000 ; i ++ {
2022-05-26 13:41:06 +02:00
idx . StorePack ( restic . NewRandomID ( ) , [ ] restic . Blob {
{
2020-11-05 22:18:00 +01:00
BlobHandle : restic . NewRandomBlobHandle ( ) ,
Length : 1234 ,
Offset : 1235 ,
2017-01-13 21:39:40 +01:00
} ,
} )
}
2022-09-11 13:51:08 +02:00
idx . Finalize ( )
2017-01-13 21:39:40 +01:00
2024-05-19 21:10:25 +02:00
id , err := idx . SaveIndex ( context . TODO ( ) , repo )
2017-10-02 15:06:39 +02:00
rtest . OK ( b , err )
2017-01-13 21:39:40 +01:00
2022-05-26 15:05:29 +02:00
b . Logf ( "index saved as %v" , id . Str ( ) )
2024-05-10 16:59:09 +02:00
fi , err := be . Stat ( context . TODO ( ) , backend . Handle { Type : restic . IndexFile , Name : id . String ( ) } )
2017-10-02 15:06:39 +02:00
rtest . OK ( b , err )
2017-01-13 21:39:40 +01:00
b . Logf ( "filesize is %v" , fi . Size )
2016-09-04 14:29:04 +02:00
b . ResetTimer ( )
for i := 0 ; i < b . N ; i ++ {
2020-11-07 18:53:59 +01:00
_ , err := loadIndex ( context . TODO ( ) , repo , id )
2017-10-02 15:06:39 +02:00
rtest . OK ( b , err )
2016-09-04 14:29:04 +02:00
}
2015-07-04 16:52:17 +02:00
}
2015-10-25 15:35:33 +01:00
// saveRandomDataBlobs generates random data blobs and saves them to the repository.
2016-09-03 13:34:04 +02:00
func saveRandomDataBlobs ( t testing . TB , repo restic . Repository , num int , sizeMax int ) {
2021-08-07 22:52:05 +02:00
var wg errgroup . Group
repo . StartPackUploader ( context . TODO ( ) , & wg )
2015-10-25 15:35:33 +01:00
for i := 0 ; i < num ; i ++ {
2017-01-13 12:20:37 +01:00
size := rand . Int ( ) % sizeMax
2015-10-25 15:35:33 +01:00
buf := make ( [ ] byte , size )
2017-01-13 12:20:37 +01:00
_ , err := io . ReadFull ( rnd , buf )
2017-10-02 15:06:39 +02:00
rtest . OK ( t , err )
2015-10-25 15:35:33 +01:00
2022-05-01 14:26:57 +02:00
_ , _ , _ , err = repo . SaveBlob ( context . TODO ( ) , restic . DataBlob , buf , restic . ID { } , false )
2017-10-02 15:06:39 +02:00
rtest . OK ( t , err )
2015-10-25 15:35:33 +01:00
}
}
func TestRepositoryIncrementalIndex ( t * testing . T ) {
2022-04-29 23:16:16 +02:00
repository . TestAllVersions ( t , testRepositoryIncrementalIndex )
}
func testRepositoryIncrementalIndex ( t * testing . T , version uint ) {
2024-05-10 16:59:09 +02:00
repo , _ := repository . TestRepositoryWithVersion ( t , version )
2020-06-06 22:20:44 +02:00
2024-05-20 00:34:54 +02:00
index . IndexFull = func ( * index . Index ) bool { return true }
2015-10-25 15:35:33 +01:00
2022-05-26 13:30:52 +02:00
// add a few rounds of packs
2015-10-25 15:35:33 +01:00
for j := 0 ; j < 5 ; j ++ {
2022-05-26 13:30:52 +02:00
// add some packs, write intermediate index
saveRandomDataBlobs ( t , repo , 20 , 1 << 15 )
2022-05-26 12:38:18 +02:00
rtest . OK ( t , repo . Flush ( context . TODO ( ) ) )
2015-10-25 15:35:33 +01:00
}
// save final index
2022-05-26 12:38:18 +02:00
rtest . OK ( t , repo . Flush ( context . TODO ( ) ) )
2015-10-25 15:35:33 +01:00
2016-08-31 20:29:54 +02:00
packEntries := make ( map [ restic . ID ] map [ restic . ID ] struct { } )
2015-10-25 15:35:33 +01:00
2018-01-21 17:25:36 +01:00
err := repo . List ( context . TODO ( ) , restic . IndexFile , func ( id restic . ID , size int64 ) error {
2020-11-07 18:53:59 +01:00
idx , err := loadIndex ( context . TODO ( ) , repo , id )
2017-10-02 15:06:39 +02:00
rtest . OK ( t , err )
2015-10-25 15:35:33 +01:00
2024-04-05 22:20:14 +02:00
rtest . OK ( t , idx . Each ( context . TODO ( ) , func ( pb restic . PackedBlob ) {
2015-10-25 15:35:33 +01:00
if _ , ok := packEntries [ pb . PackID ] ; ! ok {
2016-08-31 20:29:54 +02:00
packEntries [ pb . PackID ] = make ( map [ restic . ID ] struct { } )
2015-10-25 15:35:33 +01:00
}
packEntries [ pb . PackID ] [ id ] = struct { } { }
2024-04-05 22:20:14 +02:00
} ) )
2018-01-21 17:25:36 +01:00
return nil
} )
if err != nil {
t . Fatal ( err )
2015-10-25 15:35:33 +01:00
}
for packID , ids := range packEntries {
if len ( ids ) > 1 {
t . Errorf ( "pack %v listed in %d indexes\n" , packID , len ( ids ) )
}
}
2022-03-21 20:38:53 +01:00
}
2022-10-29 22:03:39 +02:00
func TestInvalidCompression ( t * testing . T ) {
var comp repository . CompressionMode
err := comp . Set ( "nope" )
rtest . Assert ( t , err != nil , "missing error" )
_ , err = repository . New ( nil , repository . Options { Compression : comp } )
rtest . Assert ( t , err != nil , "missing error" )
}
2024-05-09 21:39:52 +02:00
func TestListPack ( t * testing . T ) {
be := mem . New ( )
2024-05-10 16:59:09 +02:00
repo , _ := repository . TestRepositoryWithBackend ( t , & damageOnceBackend { Backend : be } , restic . StableRepoVersion , repository . Options { } )
2024-05-09 21:39:52 +02:00
buf := test . Random ( 42 , 1000 )
var wg errgroup . Group
repo . StartPackUploader ( context . TODO ( ) , & wg )
id , _ , _ , err := repo . SaveBlob ( context . TODO ( ) , restic . TreeBlob , buf , restic . ID { } , false )
rtest . OK ( t , err )
rtest . OK ( t , repo . Flush ( context . Background ( ) ) )
// setup cache after saving the blob to make sure that the damageOnceBackend damages the cached data
c := cache . TestNewCache ( t )
repo . UseCache ( c )
// Forcibly cache pack file
2024-05-19 14:56:17 +02:00
packID := repo . LookupBlob ( restic . TreeBlob , id ) [ 0 ] . PackID
2024-05-10 16:59:09 +02:00
rtest . OK ( t , be . Load ( context . TODO ( ) , backend . Handle { Type : restic . PackFile , IsMetadata : true , Name : packID . String ( ) } , 0 , 0 , func ( rd io . Reader ) error { return nil } ) )
2024-05-09 21:39:52 +02:00
// Get size to list pack
var size int64
rtest . OK ( t , repo . List ( context . TODO ( ) , restic . PackFile , func ( id restic . ID , sz int64 ) error {
if id == packID {
size = sz
}
return nil
} ) )
blobs , _ , err := repo . ListPack ( context . TODO ( ) , packID , size )
rtest . OK ( t , err )
rtest . Assert ( t , len ( blobs ) == 1 && blobs [ 0 ] . ID == id , "unexpected blobs in pack: %v" , blobs )
rtest . Assert ( t , ! c . Has ( backend . Handle { Type : restic . PackFile , Name : packID . String ( ) } ) , "tree pack should no longer be cached as ListPack does not set IsMetadata in the backend.Handle" )
}
2024-06-05 22:46:34 +02:00
func TestNoDoubleInit ( t * testing . T ) {
r , be := repository . TestRepositoryWithVersion ( t , restic . StableRepoVersion )
repo , err := repository . New ( be , repository . Options { } )
rtest . OK ( t , err )
pol := r . Config ( ) . ChunkerPolynomial
err = repo . Init ( context . TODO ( ) , r . Config ( ) . Version , test . TestPassword , & pol )
rtest . Assert ( t , strings . Contains ( err . Error ( ) , "repository master key and config already initialized" ) , "expected config exist error, got %q" , err )
// must also prevent init if only keys exist
rtest . OK ( t , be . Remove ( context . TODO ( ) , backend . Handle { Type : backend . ConfigFile } ) )
err = repo . Init ( context . TODO ( ) , r . Config ( ) . Version , test . TestPassword , & pol )
rtest . Assert ( t , strings . Contains ( err . Error ( ) , "repository already contains keys" ) , "expected already contains keys error, got %q" , err )
2024-06-13 20:00:20 +02:00
// must also prevent init if a snapshot exists and keys were deleted
var data [ 32 ] byte
hash := restic . Hash ( data [ : ] )
rtest . OK ( t , be . Save ( context . TODO ( ) , backend . Handle { Type : backend . SnapshotFile , Name : hash . String ( ) } , backend . NewByteReader ( data [ : ] , be . Hasher ( ) ) ) )
rtest . OK ( t , be . List ( context . TODO ( ) , restic . KeyFile , func ( fi backend . FileInfo ) error {
return be . Remove ( context . TODO ( ) , backend . Handle { Type : restic . KeyFile , Name : fi . Name } )
} ) )
err = repo . Init ( context . TODO ( ) , r . Config ( ) . Version , test . TestPassword , & pol )
rtest . Assert ( t , strings . Contains ( err . Error ( ) , "repository already contains snapshots" ) , "expected already contains snapshots error, got %q" , err )
2024-06-05 22:46:34 +02:00
}