mirror of
https://github.com/kopia/kopia.git
synced 2026-01-04 12:37:52 -05:00
331 lines
7.1 KiB
Go
331 lines
7.1 KiB
Go
package fio
|
|
|
|
import (
|
|
"os"
|
|
"path/filepath"
|
|
"testing"
|
|
|
|
"github.com/stretchr/testify/require"
|
|
)
|
|
|
|
func TestWriteFiles(t *testing.T) {
|
|
r, err := NewRunner()
|
|
require.NoError(t, err)
|
|
|
|
defer r.Cleanup()
|
|
|
|
relativeWritePath := "some/path/to/check"
|
|
writeFileSizeB := int64(256 * 1024) // 256 KiB
|
|
numFiles := 13
|
|
fioOpt := Options{}.WithFileSize(writeFileSizeB).WithNumFiles(numFiles).WithBlockSize(4096)
|
|
|
|
// Test a call to WriteFiles
|
|
err = r.WriteFiles(relativeWritePath, fioOpt)
|
|
require.NoError(t, err)
|
|
|
|
fullPath := filepath.Join(r.LocalDataDir, relativeWritePath)
|
|
dirEntries, err := os.ReadDir(fullPath)
|
|
require.NoError(t, err)
|
|
|
|
if got, want := len(dirEntries), numFiles; got != want {
|
|
t.Errorf("Did not get expected number of files %v (actual) != %v (expected", got, want)
|
|
}
|
|
|
|
sizeTot := int64(0)
|
|
|
|
for _, entry := range dirEntries {
|
|
fi, err := entry.Info()
|
|
if err != nil {
|
|
t.Fatalf("Failed to read file info: %v", err)
|
|
}
|
|
|
|
sizeTot += fi.Size()
|
|
}
|
|
|
|
want := writeFileSizeB * int64(numFiles)
|
|
if got := sizeTot; got != want {
|
|
t.Errorf("Did not get the expected amount of data written %v (actual) != %v (expected)", got, want)
|
|
}
|
|
}
|
|
|
|
func TestWriteFilesAtDepth(t *testing.T) {
|
|
r, err := NewRunner()
|
|
require.NoError(t, err)
|
|
|
|
defer r.Cleanup()
|
|
|
|
for _, tt := range []struct {
|
|
name string
|
|
depth int
|
|
expFileCount int
|
|
}{
|
|
{
|
|
name: "Test depth zero, 1 file",
|
|
depth: 0,
|
|
expFileCount: 1,
|
|
},
|
|
{
|
|
name: "Test depth zero, multiple files",
|
|
depth: 0,
|
|
expFileCount: 10,
|
|
},
|
|
{
|
|
name: "Test depth 1, 1 file",
|
|
depth: 1,
|
|
expFileCount: 1,
|
|
},
|
|
{
|
|
name: "Test depth 1, multiple files",
|
|
depth: 1,
|
|
expFileCount: 10,
|
|
},
|
|
{
|
|
name: "Test depth 10, 1 file",
|
|
depth: 10,
|
|
expFileCount: 1,
|
|
},
|
|
{
|
|
name: "Test depth 10, multiple files",
|
|
depth: 10,
|
|
expFileCount: 10,
|
|
},
|
|
} {
|
|
t.Log(tt.name)
|
|
|
|
testWriteAtDepth(t, r, tt.depth, tt.expFileCount)
|
|
}
|
|
}
|
|
|
|
func testWriteAtDepth(t *testing.T, r *Runner, depth, expFileCount int) {
|
|
t.Helper()
|
|
|
|
testSubdir := "test"
|
|
testDirAbs := filepath.Join(r.LocalDataDir, testSubdir)
|
|
|
|
sizeB := int64(128 * 1024 * 1024)
|
|
fioOpt := Options{}.WithSize(sizeB).WithNumFiles(expFileCount)
|
|
|
|
err := r.WriteFilesAtDepth(testSubdir, depth, fioOpt)
|
|
require.NoError(t, err)
|
|
|
|
defer r.DeleteRelDir(testSubdir)
|
|
|
|
dirCount := 0
|
|
fileCount := 0
|
|
|
|
err = filepath.Walk(testDirAbs, func(path string, info os.FileInfo, err error) error {
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
if info.IsDir() {
|
|
dirCount++
|
|
} else {
|
|
fileCount++
|
|
}
|
|
|
|
return nil
|
|
})
|
|
require.NoError(t, err)
|
|
|
|
if got, want := fileCount, expFileCount; got != want {
|
|
t.Errorf("Expected %v files, only found %v", want, got)
|
|
}
|
|
|
|
// Expect number of directories to equal the requested depth, plus one
|
|
// since the walk starts in a directory
|
|
if got, want := dirCount, depth+1; got != want {
|
|
t.Errorf("Expected %v directories, but found %v", want, got)
|
|
}
|
|
}
|
|
|
|
func TestDeleteFilesAtDepth(t *testing.T) {
|
|
r, err := NewRunner()
|
|
require.NoError(t, err)
|
|
|
|
defer r.Cleanup()
|
|
|
|
for _, tt := range []struct {
|
|
name string
|
|
wrDepth int
|
|
delDepth int
|
|
expDirCount int
|
|
expErr bool
|
|
}{
|
|
{
|
|
name: "Test write files at depth 1, delete a directory at depth 0 (expect error - can't delete root directory)",
|
|
wrDepth: 1,
|
|
delDepth: 0,
|
|
expDirCount: 1,
|
|
expErr: true,
|
|
},
|
|
{
|
|
name: "Test write files at depth 1, delete a directory at depth 1",
|
|
wrDepth: 1,
|
|
delDepth: 1,
|
|
expDirCount: 0,
|
|
expErr: false,
|
|
},
|
|
{
|
|
name: "Test write files at depth 10, delete a directory at depth 9",
|
|
wrDepth: 10,
|
|
delDepth: 9,
|
|
expDirCount: 8,
|
|
expErr: false,
|
|
},
|
|
{
|
|
name: "Test write files at depth 10, delete a directory at depth 10",
|
|
wrDepth: 10,
|
|
delDepth: 10,
|
|
expDirCount: 9,
|
|
expErr: false,
|
|
},
|
|
{
|
|
name: "Test write files at depth 1, delete a directory at depth 11 (expect error)",
|
|
wrDepth: 1,
|
|
delDepth: 11,
|
|
expDirCount: 1,
|
|
expErr: true,
|
|
},
|
|
} {
|
|
t.Log(tt.name)
|
|
|
|
testDeleteAtDepth(t, r, tt.wrDepth, tt.delDepth, tt.expDirCount, tt.expErr)
|
|
}
|
|
}
|
|
|
|
func testDeleteAtDepth(t *testing.T, r *Runner, wrDepth, delDepth, expDirCount int, expErr bool) {
|
|
t.Helper()
|
|
|
|
testSubdir := "test"
|
|
testDirAbs := filepath.Join(r.LocalDataDir, testSubdir)
|
|
|
|
sizeB := int64(128 * 1024 * 1024)
|
|
numFiles := 2
|
|
fioOpt := Options{}.WithSize(sizeB).WithNumFiles(numFiles)
|
|
|
|
err := r.WriteFilesAtDepth(testSubdir, wrDepth, fioOpt)
|
|
require.NoError(t, err)
|
|
|
|
defer r.DeleteRelDir(testSubdir)
|
|
|
|
err = r.DeleteDirAtDepth(testSubdir, delDepth)
|
|
if expErr {
|
|
if err == nil {
|
|
t.Fatalf("Expected error but got none")
|
|
}
|
|
} else {
|
|
require.NoError(t, err)
|
|
}
|
|
|
|
dirCount := 0
|
|
fileCount := 0
|
|
|
|
err = filepath.Walk(testDirAbs, func(path string, info os.FileInfo, err error) error {
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
if info.IsDir() {
|
|
dirCount++
|
|
} else {
|
|
fileCount++
|
|
}
|
|
|
|
return nil
|
|
})
|
|
require.NoError(t, err)
|
|
|
|
// Expect number of directories to equal the requested depth, plus one
|
|
// since the walk starts in a directory
|
|
if got, want := dirCount, expDirCount+1; got != want {
|
|
t.Errorf("Expected %v directories, but found %v", want, got)
|
|
}
|
|
}
|
|
|
|
func TestDeleteContentsAtDepth(t *testing.T) {
|
|
for _, tc := range []struct {
|
|
prob float32
|
|
expFileCountChecker func(t *testing.T, fileCount int)
|
|
}{
|
|
{
|
|
prob: 0.0,
|
|
expFileCountChecker: func(t *testing.T, fileCount int) {
|
|
t.Helper()
|
|
|
|
if fileCount != 100 {
|
|
t.Error("some files were deleted despite 0% probability")
|
|
}
|
|
},
|
|
},
|
|
{
|
|
prob: 1.0,
|
|
expFileCountChecker: func(t *testing.T, fileCount int) {
|
|
t.Helper()
|
|
|
|
if fileCount != 0 {
|
|
t.Error("not all files were deleted despite 100% probability")
|
|
}
|
|
},
|
|
},
|
|
{
|
|
prob: 0.5,
|
|
expFileCountChecker: func(t *testing.T, fileCount int) {
|
|
t.Helper()
|
|
|
|
// Broad check: just make sure a 50% probability deleted something.
|
|
// Extremely improbable that this causes a false failure;
|
|
// akin to 100 coin flips all landing on the same side.
|
|
if fileCount <= 0 || fileCount >= 100 {
|
|
t.Error("expected some but not all files to be deleted")
|
|
}
|
|
},
|
|
},
|
|
} {
|
|
testDeleteContentsAtDepth(t, tc.prob, tc.expFileCountChecker)
|
|
}
|
|
}
|
|
|
|
//nolint:thelper
|
|
func testDeleteContentsAtDepth(t *testing.T, prob float32, checker func(t *testing.T, fileCount int)) {
|
|
r, err := NewRunner()
|
|
require.NoError(t, err)
|
|
|
|
defer r.Cleanup()
|
|
|
|
testSubdir := "test"
|
|
testDirAbs := filepath.Join(r.LocalDataDir, testSubdir)
|
|
|
|
sizeB := int64(128 * 1024 * 1024)
|
|
numFiles := 100
|
|
fioOpt := Options{}.WithSize(sizeB).WithNumFiles(numFiles)
|
|
|
|
wrDepth := 3
|
|
err = r.WriteFilesAtDepth(testSubdir, wrDepth, fioOpt)
|
|
require.NoError(t, err)
|
|
|
|
defer r.DeleteRelDir(testSubdir)
|
|
|
|
delDepth := 3
|
|
err = r.DeleteContentsAtDepth(testSubdir, delDepth, prob)
|
|
require.NoError(t, err)
|
|
|
|
fileCount := 0
|
|
|
|
err = filepath.Walk(testDirAbs, func(path string, info os.FileInfo, err error) error {
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
if !info.IsDir() {
|
|
fileCount++
|
|
}
|
|
|
|
return nil
|
|
})
|
|
|
|
require.NoError(t, err)
|
|
|
|
checker(t, fileCount)
|
|
}
|