2022-03-28 20:23:47 +00:00
|
|
|
//go:build !windows
|
|
|
|
// +build !windows
|
2018-09-27 12:59:33 +00:00
|
|
|
|
|
|
|
package restorer
|
|
|
|
|
|
|
|
import (
|
|
|
|
"context"
|
|
|
|
"os"
|
|
|
|
"path/filepath"
|
|
|
|
"syscall"
|
|
|
|
"testing"
|
2023-05-08 18:49:41 +00:00
|
|
|
"time"
|
2018-09-27 12:59:33 +00:00
|
|
|
|
|
|
|
"github.com/restic/restic/internal/repository"
|
|
|
|
"github.com/restic/restic/internal/restic"
|
|
|
|
rtest "github.com/restic/restic/internal/test"
|
2023-05-08 18:49:41 +00:00
|
|
|
restoreui "github.com/restic/restic/internal/ui/restore"
|
2018-09-27 12:59:33 +00:00
|
|
|
)
|
|
|
|
|
|
|
|
func TestRestorerRestoreEmptyHardlinkedFileds(t *testing.T) {
|
2022-12-11 09:41:22 +00:00
|
|
|
repo := repository.TestRepository(t)
|
2018-09-27 12:59:33 +00:00
|
|
|
|
2022-10-03 12:48:14 +00:00
|
|
|
sn, _ := saveSnapshot(t, repo, Snapshot{
|
2018-09-27 12:59:33 +00:00
|
|
|
Nodes: map[string]Node{
|
|
|
|
"dirtest": Dir{
|
|
|
|
Nodes: map[string]Node{
|
|
|
|
"file1": File{Links: 2, Inode: 1},
|
|
|
|
"file2": File{Links: 2, Inode: 1},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
})
|
|
|
|
|
2023-05-18 17:21:28 +00:00
|
|
|
res := NewRestorer(repo, sn, false, nil)
|
2018-09-27 12:59:33 +00:00
|
|
|
|
|
|
|
res.SelectFilter = func(item string, dstpath string, node *restic.Node) (selectedForRestore bool, childMayBeSelected bool) {
|
|
|
|
return true, true
|
|
|
|
}
|
|
|
|
|
2022-12-09 12:42:33 +00:00
|
|
|
tempdir := rtest.TempDir(t)
|
2018-09-27 12:59:33 +00:00
|
|
|
ctx, cancel := context.WithCancel(context.Background())
|
|
|
|
defer cancel()
|
|
|
|
|
2022-10-03 12:48:14 +00:00
|
|
|
err := res.RestoreTo(ctx, tempdir)
|
2018-09-27 12:59:33 +00:00
|
|
|
rtest.OK(t, err)
|
|
|
|
|
|
|
|
f1, err := os.Stat(filepath.Join(tempdir, "dirtest/file1"))
|
|
|
|
rtest.OK(t, err)
|
|
|
|
rtest.Equals(t, int64(0), f1.Size())
|
|
|
|
s1, ok1 := f1.Sys().(*syscall.Stat_t)
|
|
|
|
|
|
|
|
f2, err := os.Stat(filepath.Join(tempdir, "dirtest/file2"))
|
|
|
|
rtest.OK(t, err)
|
|
|
|
rtest.Equals(t, int64(0), f2.Size())
|
|
|
|
s2, ok2 := f2.Sys().(*syscall.Stat_t)
|
|
|
|
|
|
|
|
if ok1 && ok2 {
|
|
|
|
rtest.Equals(t, s1.Ino, s2.Ino)
|
|
|
|
}
|
|
|
|
}
|
2020-02-26 20:48:05 +00:00
|
|
|
|
2022-09-04 09:23:31 +00:00
|
|
|
func getBlockCount(t *testing.T, filename string) int64 {
|
2020-02-26 20:48:05 +00:00
|
|
|
fi, err := os.Stat(filename)
|
|
|
|
rtest.OK(t, err)
|
|
|
|
st := fi.Sys().(*syscall.Stat_t)
|
|
|
|
if st == nil {
|
2022-09-04 09:23:31 +00:00
|
|
|
return -1
|
2020-02-26 20:48:05 +00:00
|
|
|
}
|
2022-09-04 09:23:31 +00:00
|
|
|
return st.Blocks
|
2020-02-26 20:48:05 +00:00
|
|
|
}
|
2023-05-08 18:49:41 +00:00
|
|
|
|
|
|
|
type printerMock struct {
|
|
|
|
filesFinished, filesTotal, allBytesWritten, allBytesTotal uint64
|
|
|
|
}
|
|
|
|
|
2023-05-18 17:27:38 +00:00
|
|
|
func (p *printerMock) Update(_, _, _, _ uint64, _ time.Duration) {
|
2023-05-08 18:49:41 +00:00
|
|
|
}
|
2023-05-18 17:27:38 +00:00
|
|
|
func (p *printerMock) Finish(filesFinished, filesTotal, allBytesWritten, allBytesTotal uint64, _ time.Duration) {
|
2023-05-08 18:49:41 +00:00
|
|
|
p.filesFinished = filesFinished
|
|
|
|
p.filesTotal = filesTotal
|
|
|
|
p.allBytesWritten = allBytesWritten
|
|
|
|
p.allBytesTotal = allBytesTotal
|
|
|
|
}
|
|
|
|
|
|
|
|
func TestRestorerProgressBar(t *testing.T) {
|
|
|
|
repo := repository.TestRepository(t)
|
|
|
|
|
|
|
|
sn, _ := saveSnapshot(t, repo, Snapshot{
|
|
|
|
Nodes: map[string]Node{
|
|
|
|
"dirtest": Dir{
|
|
|
|
Nodes: map[string]Node{
|
|
|
|
"file1": File{Links: 2, Inode: 1, Data: "foo"},
|
|
|
|
"file2": File{Links: 2, Inode: 1, Data: "foo"},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
"file2": File{Links: 1, Inode: 2, Data: "example"},
|
|
|
|
},
|
|
|
|
})
|
|
|
|
|
|
|
|
mock := &printerMock{}
|
|
|
|
progress := restoreui.NewProgress(mock, 0)
|
2023-05-18 17:21:28 +00:00
|
|
|
res := NewRestorer(repo, sn, false, progress)
|
2023-05-08 18:49:41 +00:00
|
|
|
res.SelectFilter = func(item string, dstpath string, node *restic.Node) (selectedForRestore bool, childMayBeSelected bool) {
|
|
|
|
return true, true
|
|
|
|
}
|
|
|
|
|
|
|
|
tempdir := rtest.TempDir(t)
|
|
|
|
ctx, cancel := context.WithCancel(context.Background())
|
|
|
|
defer cancel()
|
|
|
|
|
|
|
|
err := res.RestoreTo(ctx, tempdir)
|
|
|
|
rtest.OK(t, err)
|
|
|
|
progress.Finish()
|
|
|
|
|
|
|
|
const filesFinished = 4
|
|
|
|
const filesTotal = filesFinished
|
|
|
|
const allBytesWritten = 10
|
|
|
|
const allBytesTotal = allBytesWritten
|
|
|
|
rtest.Assert(t, mock.filesFinished == filesFinished, "filesFinished: expected %v, got %v", filesFinished, mock.filesFinished)
|
|
|
|
rtest.Assert(t, mock.filesTotal == filesTotal, "filesTotal: expected %v, got %v", filesTotal, mock.filesTotal)
|
|
|
|
rtest.Assert(t, mock.allBytesWritten == allBytesWritten, "allBytesWritten: expected %v, got %v", allBytesWritten, mock.allBytesWritten)
|
|
|
|
rtest.Assert(t, mock.allBytesTotal == allBytesTotal, "allBytesTotal: expected %v, got %v", allBytesTotal, mock.allBytesTotal)
|
|
|
|
}
|