storage/internal/tempdir/tempdir_test.go

287 lines
7.2 KiB
Go

package tempdir
import (
"fmt"
"os"
"path/filepath"
"strings"
"testing"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
)
func TestTempDirAdd(t *testing.T) {
rootDir := t.TempDir()
td, err := NewTempDir(rootDir)
require.NoError(t, err)
defer func() {
assert.NoError(t, td.Cleanup())
}()
filePath := filepath.Join(t.TempDir(), "testfile.txt")
err = os.WriteFile(filePath, []byte("test content"), 0o644)
require.NoError(t, err)
err = td.StageDeletion(filePath)
require.NoError(t, err)
assert.NotEmpty(t, td.tempDirPath)
assert.NotNil(t, td.tempDirLock)
assert.NotEmpty(t, td.tempDirLockPath)
files, err := os.ReadDir(td.tempDirPath)
require.NoError(t, err)
assert.Len(t, files, 1)
assert.True(t, strings.HasPrefix(files[0].Name(), "0-"))
assert.True(t, strings.HasSuffix(files[0].Name(), "testfile.txt"))
_, err = os.Stat(filePath)
assert.True(t, os.IsNotExist(err))
}
func TestTempDirAddMultipleFiles(t *testing.T) {
rootDir := t.TempDir()
td, err := NewTempDir(rootDir)
require.NoError(t, err)
defer func() {
assert.NoError(t, td.Cleanup())
}()
tempDir := t.TempDir()
for i := 0; i < 3; i++ {
testFile := filepath.Join(tempDir, fmt.Sprintf("testfile%d.txt", i))
err = os.WriteFile(testFile, []byte(fmt.Sprintf("content %d", i)), 0o644)
require.NoError(t, err)
err = td.StageDeletion(testFile)
require.NoError(t, err)
}
files, err := os.ReadDir(td.tempDirPath)
require.NoError(t, err)
assert.Len(t, files, 3)
for i, file := range files {
assert.Equal(t, filepath.Base(file.Name()), fmt.Sprintf("%d-testfile%d.txt", i, i))
}
}
func TestTempDirCleanup(t *testing.T) {
rootDir := t.TempDir()
td, err := NewTempDir(rootDir)
require.NoError(t, err)
testFile := filepath.Join(t.TempDir(), "testfile.txt")
require.NoError(t, os.WriteFile(testFile, []byte("test"), 0o644))
require.NoError(t, td.StageDeletion(testFile))
tempDirPath := td.tempDirPath
lockPath := td.tempDirLockPath
_, err = os.Stat(tempDirPath)
assert.NoError(t, err)
_, err = os.Stat(lockPath)
assert.NoError(t, err)
require.NoError(t, td.Cleanup())
_, err = os.Stat(tempDirPath)
assert.True(t, os.IsNotExist(err))
_, err = os.Stat(lockPath)
assert.True(t, os.IsNotExist(err))
assert.Empty(t, td.tempDirPath)
assert.Nil(t, td.tempDirLock)
assert.Empty(t, td.tempDirLockPath)
}
func TestTempDirCleanupNotInit(t *testing.T) {
rootDir := t.TempDir()
td, err := NewTempDir(rootDir)
require.NoError(t, err)
assert.NoError(t, td.Cleanup())
assert.NoError(t, td.Cleanup())
}
func TestTempDirReInitAfterCleanup(t *testing.T) {
rootDir := t.TempDir()
td, err := NewTempDir(rootDir)
require.NoError(t, err)
testFile1 := filepath.Join(t.TempDir(), "testfile1.txt")
err = os.WriteFile(testFile1, []byte("test1"), 0o644)
require.NoError(t, err)
require.NoError(t, td.StageDeletion(testFile1))
require.NoError(t, td.Cleanup())
testFile2 := filepath.Join(t.TempDir(), "testfile2.txt")
require.NoError(t, os.WriteFile(testFile2, []byte("test2"), 0o644))
require.Error(t, td.StageDeletion(testFile2))
assert.Empty(t, td.tempDirPath)
assert.Nil(t, td.tempDirLock)
}
func TestListPotentialStaleDirs(t *testing.T) {
rootDir := t.TempDir()
expectedIds := map[string]struct{}{}
for i := 0; i < 3; i++ {
lockfile, err := os.CreateTemp(rootDir, tempdirLockPrefix)
assert.NoError(t, err)
lockfileName := filepath.Base(lockfile.Name())
lockfile.Close()
id := strings.TrimPrefix(lockfileName, tempdirLockPrefix)
tempDirPath := filepath.Join(rootDir, tempDirPrefix+id)
err = os.MkdirAll(tempDirPath, 0o755)
require.NoError(t, err)
expectedIds[id] = struct{}{}
}
ids, err := listPotentialStaleDirs(rootDir)
require.NoError(t, err)
assert.Equal(t, expectedIds, ids)
}
func TestListPotentialStaleDirsNonexistentDir(t *testing.T) {
nonexistentDir := filepath.Join(t.TempDir(), "nonexistent")
ids, err := listPotentialStaleDirs(nonexistentDir)
assert.NoError(t, err)
assert.Nil(t, ids)
}
func TestRecoverStaleDirs(t *testing.T) {
rootDir := t.TempDir()
staleDir := filepath.Join(rootDir, tempDirPrefix+"stale")
staleLock := filepath.Join(rootDir, tempdirLockPrefix+"stale")
require.NoError(t, os.MkdirAll(staleDir, 0o755))
require.NoError(t, os.WriteFile(filepath.Join(staleDir, "somefile"), []byte("data"), 0o644))
require.NoError(t, os.WriteFile(staleLock, []byte{}, 0o644))
_, err := os.Stat(staleDir)
assert.NoError(t, err)
_, err = os.Stat(staleLock)
assert.NoError(t, err)
assert.NoError(t, RecoverStaleDirs(rootDir))
_, err = os.Stat(staleDir)
assert.True(t, os.IsNotExist(err))
_, err = os.Stat(staleLock)
assert.True(t, os.IsNotExist(err))
}
func TestRecoverStaleDirsSkipsActiveDirs(t *testing.T) {
rootDir := t.TempDir()
td, err := NewTempDir(rootDir)
require.NoError(t, err)
testFile := filepath.Join(t.TempDir(), "testfile.txt")
require.NoError(t, os.WriteFile(testFile, []byte("test"), 0o644))
require.NoError(t, td.StageDeletion(testFile))
defer func() {
assert.NoError(t, td.Cleanup())
}()
activeTempDir := td.tempDirPath
activeLock := td.tempDirLockPath
staleDir := filepath.Join(rootDir, tempDirPrefix+"stale")
staleLock := filepath.Join(rootDir, tempdirLockPrefix+"stale")
require.NoError(t, os.MkdirAll(staleDir, 0o755))
require.NoError(t, os.WriteFile(staleLock, []byte{}, 0o644))
assert.NoError(t, RecoverStaleDirs(rootDir))
_, err = os.Stat(activeTempDir)
assert.NoError(t, err)
_, err = os.Stat(activeLock)
assert.NoError(t, err)
_, err = os.Stat(staleDir)
assert.True(t, os.IsNotExist(err))
_, err = os.Stat(staleLock)
assert.True(t, os.IsNotExist(err))
}
func TestTempDirMultipleInstances(t *testing.T) {
rootDir := t.TempDir()
td1, err := NewTempDir(rootDir)
require.NoError(t, err)
defer func() {
assert.NoError(t, td1.Cleanup())
}()
td2, err := NewTempDir(rootDir)
require.NoError(t, err)
defer func() {
assert.NoError(t, td2.Cleanup())
}()
testFile1 := filepath.Join(t.TempDir(), "testfile1.txt")
require.NoError(t, os.WriteFile(testFile1, []byte("test1"), 0o644))
require.NoError(t, td1.StageDeletion(testFile1))
testFile2 := filepath.Join(t.TempDir(), "testfile2.txt")
require.NoError(t, os.WriteFile(testFile2, []byte("test2"), 0o644))
require.NoError(t, td2.StageDeletion(testFile2))
assert.NotEqual(t, td1.tempDirPath, td2.tempDirPath)
assert.NotEqual(t, td1.tempDirLockPath, td2.tempDirLockPath)
_, err = os.Stat(td1.tempDirPath)
assert.NoError(t, err)
_, err = os.Stat(td2.tempDirPath)
assert.NoError(t, err)
}
func TestTempDirFileNaming(t *testing.T) {
rootDir := t.TempDir()
td, err := NewTempDir(rootDir)
require.NoError(t, err)
defer func() {
assert.NoError(t, td.Cleanup())
}()
tempDir := t.TempDir()
testCases := []string{
"simple.txt",
"file with spaces.txt",
"file-with-dashes.txt",
"file.with.dots.txt",
}
for i, filename := range testCases {
testFile := filepath.Join(tempDir, filename)
require.NoError(t, os.WriteFile(testFile, []byte("test"), 0o644))
require.NoError(t, td.StageDeletion(testFile))
files, err := os.ReadDir(td.tempDirPath)
require.NoError(t, err)
found := false
expectedName := fmt.Sprintf("%d-%s", i, filename)
for _, file := range files {
if file.Name() == expectedName {
found = true
break
}
}
assert.True(t, found, "Expected file %s not found", expectedName)
}
}