Files
kopia/tests/end_to_end_test/ecc_test.go
2025-04-26 13:01:20 -07:00

150 lines
3.1 KiB
Go

package endtoend_test
import (
"math"
"math/rand"
"os"
"path/filepath"
"testing"
"github.com/stretchr/testify/require"
"github.com/kopia/kopia/internal/testutil"
"github.com/kopia/kopia/tests/clitestutil"
"github.com/kopia/kopia/tests/testenv"
)
func (s *formatSpecificTestSuite) TestNoECC(t *testing.T) {
t.Parallel()
const mb = 1024 * 1024
runner := testenv.NewInProcRunner(t)
e := testenv.NewCLITest(t, s.formatFlags, runner)
defer e.RunAndExpectSuccess(t, "repo", "disconnect")
e.RunAndExpectSuccess(t, "repo", "create", "filesystem", "--flat", "--path", e.RepoDir)
dataDir := testutil.TempDirectory(t)
var data [mb]byte
for i := range data {
data[i] = byte(i%254) + 1
}
require.NoError(t, os.WriteFile(filepath.Join(dataDir, "some-file1"), data[:], 0o600))
e.RunAndExpectSuccess(t, "snapshot", "create", dataDir)
repoSize, err := dirSize(e.RepoDir)
require.NoError(t, err)
require.Less(t, repoSize, int64(math.Round(1.1*mb)))
}
func (s *formatSpecificTestSuite) TestECC(t *testing.T) {
t.Parallel()
const mb = 1024 * 1024
runner := testenv.NewInProcRunner(t)
e := testenv.NewCLITest(t, s.formatFlags, runner)
defer e.RunAndExpectSuccess(t, "repo", "disconnect")
e.RunAndExpectSuccess(t, "repo", "create", "filesystem", "--flat", "--path", e.RepoDir, "--ecc-overhead-percent=50")
dataDir := testutil.TempDirectory(t)
var data [mb]byte
for i := range data {
data[i] = byte(i%254) + 1
}
fileName := "some-file1"
require.NoError(t, os.WriteFile(filepath.Join(dataDir, fileName), data[:], 0o600))
e.RunAndExpectSuccess(t, "snapshot", "create", dataDir)
repoSize, err := dirSize(e.RepoDir)
require.NoError(t, err)
// ECC is not supported in version 1
if s.formatVersion == 1 {
require.Less(t, repoSize, int64(math.Round(1.1*mb)))
return
}
require.GreaterOrEqual(t, repoSize, int64(math.Round(1.5*mb)))
err = s.flipOneByteFromEachFile(e)
require.NoError(t, err)
si := clitestutil.ListSnapshotsAndExpectSuccess(t, e, dataDir)
snapID := si[0].Snapshots[0].SnapshotID
restoreDir := testutil.TempDirectory(t)
e.RunAndExpectSuccess(t, "restore", snapID, restoreDir)
restoreData, err := os.ReadFile(filepath.Join(restoreDir, fileName))
require.NoError(t, err)
require.Equal(t, data[:], restoreData)
}
func (s *formatSpecificTestSuite) flipOneByteFromEachFile(e *testenv.CLITest) error {
return filepath.Walk(e.RepoDir, func(path string, info os.FileInfo, err error) error {
if err != nil {
return err
}
if info.IsDir() {
return nil
}
if info.Name() == "kopia.repository.f" || info.Name() == ".shards" {
return nil
}
bytes, err := os.ReadFile(path)
if err != nil {
return err
}
c := rand.Intn(len(bytes))
if bytes[c] >= 128 {
bytes[c] = 0
} else {
bytes[c] = 255
}
err = os.WriteFile(path, bytes, info.Mode())
if err != nil {
return err
}
return nil
})
}
func dirSize(path string) (int64, error) {
var size int64
err := filepath.Walk(path, func(_ string, info os.FileInfo, err error) error {
if err != nil {
return err
}
if !info.IsDir() {
size += info.Size()
}
return nil
})
return size, err
}